In continuation of my attempts to understand std::enable_if usage - c++14

In this piece of code:
#include <iostream>
#include <cstdlib>
#include <type_traits>
#include <ios>
using std::enable_if;
using std::is_same;
using std::boolalpha;
using std::cout;
using std::endl;
template <typename T>
struct S {
S(): t(static_cast<T>(NULL)) { }
// void type() {
// cout << boolalpha;
// cout << is_same<T,int>::value << endl;
// }
template <typename enable_if<is_same<T,int>::value,T>::type>
void type() {
cout << boolalpha << true << endl;
}
T t;
};
int main(){
S<int> s;
s.type();
return(0);
}
I get successful compilation and output for the method type() implemented as a non-template function; however, for the same method implemented as a template function using std::enable_if I get the following compilation error:
so_main.cpp:23:11: error: no matching member function for call to 'type'
s.type();
~~^~~~
so_main.cpp:15:73: note: candidate template ignored: couldn't infer template argument ''
template<typename enable_if<is_same<T,int>::value,T>::type>void type(){cout << boolalpha << true << endl;}
^
1 error generated.
My understanding is that the logic implemented in both cases is similar.
When the method is non-template, the type for T is corroborated as int. However, when std::enable_if is used to enable the template function for the same condition (i.e., T is int), the code does not compile.

This is because SFINAE only works on template parameters pertaining to the template itself. The standard calls that immediate context. In your code example, T is a template parameter of the class template, not of the member function template.
You can circumvent this by giving your function a dummy template parameter that defaults to T, and using SFINAE on it instead, like this:
template <typename U=T>
typename enable_if<is_same<U,int>::value>::type type() {
cout << boolalpha << true << endl;
}

Related

How to work out types required for std::for_each lambda function

I am confused about how to work out what type is required to use a lambda function in std::for_each. It seems I cannot use auto in this case as a parameter (Visual Studio 2013 complains anyway).
In the code below I would have thought I would use sections as the type for the for_each function, but in fact I have to use
const std::pair<std::string, std::unordered_map<std::string, std::string> >
And for the 'inner' type in this case what do I use?
My main question is how I work out what type to use?
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
// key=value pairs within a section
typedef std::unordered_map<std::string, std::string> keyvalue;
// [section1] - top level
typedef std::unordered_map< std::string, std::unordered_map<std::string, std::string> > sections;
class config
{
public:
config() {
setup();
}
typedef sections::iterator iterator;
iterator begin() { return sections_.begin(); }
iterator end() { return sections_.end(); }
private:
sections sections_;
void setup() {
// obviously we wouldn't hard code like this in a real program
sections_["programming languages"].insert(std::make_pair("C", "imperative"));
sections_["programming languages"].insert(std::make_pair("C++", "OOP"));
sections_["programming languages"].insert(std::make_pair("Java", "OOP"));
sections_["programming languages"].insert(std::make_pair("Haskell", "functional"));
sections_["programming languages"].insert(std::make_pair("Prolog", "logic"));
}
};
int main() {
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const std::pair<std::string, std::unordered_map<std::string, std::string> > sec) {
std::cout << "section name: " << sec.first << std::endl;
// what is inner type - thought it would be keyvalue ???
//std::for_each(sec.second.begin(), sec.second.end(), [](const keyvalue& pr) {
//std::cout << "first: " << pr << std::endl;
//});
});
// I thought type would be sections ???
//std::for_each(cfg.begin(), cfg.end(), [](const sections& sec) {
// std::cout << "section name: " << sec.first << std::endl;
//});
}
You can also use decltype for this purpose like this:
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const decltype(*cfg.begin())& sec) {
std::cout << "section name: " << sec.first << std::endl;
std::for_each(sec.second.begin(), sec.second.end(), [](const decltype(*sec.second.begin())& pr) {
std::cout << "first: " << pr.first << std::endl;
});
});
I'm not 100% certain how reference types affect this, so removing it might be more appropriate like const std::remove_reference<decltype(*cfg.begin())>::type& sec
Although it should be noted that VS2013 ItelliSense has trouble with decltype and will mark it as an error even if it compiles fine.
STL containers always define a value_type so in that case you can use decltype(inst)::value_type and you don't need the remove_reference shenanigans. So I would advise you to also add a value_type typedef to your type like this:
class config
{
public:
typedef sections::value_type value_type;
Then you can do:
config cfg;
std::for_each(cfg.begin(), cfg.end(), [](const decltype(cfg)::value_type& sec) {
std::cout << "section name: " << sec.first << std::endl;
std::for_each(sec.second.begin(), sec.second.end(), [](const decltype(sec.second)::value_type& pr) {
std::cout << "first: " << pr.first << std::endl;
});
});

c++11 dedicated "proxy constructors" delegating to private univeral reference constructor?

Reading Scott Meyer's book "Effective Modern C++", Item 24 (and following), and Item 41, I wonder that this book opposes:
the individual constructors for lvalue and rvalue parameters
to
a template'd universal constructor solution
It says, that 1. has the disadvantage to duplicate code.
Whereas 2. has the disadvantage to potentially being used for unwanted types.
I wonder why the book does not mention a mixed model - as in the example code shown below.
It uses type-safe dedicated constructors for lvalue and rvalue but delegates to a single (private) generic implementation for "universal reference".
This avoids unwanted template types of a public "universal reference" constructor.
So is there is anything wrong with the approach below? Something I missed?
#include <iostream>
#include <string>
class MyClass
{
private:
enum class Dummy { Nop = 0 } ;
template <class T>
MyClass(Dummy, T&& data)
: _data(std::forward<T>(data))
{
std::cout << "MyClass universal reference template c'tor" << std::endl;
}
public:
// proxy c'tors delegating to universal reference c'tor
MyClass (std::string const & data)
: MyClass(Dummy::Nop, data)
{
std::cout << "MyClass lvalue c'tor" << std::endl;
}
MyClass (std::string && data)
: MyClass(Dummy::Nop, std::move(data))
{
std::cout << "MyClass rvalue c'tor" << std::endl;
}
private:
std::string _data;
};
int main(int, char**)
{
{
std::string str("demo");
MyClass myClass(str);
}
{
MyClass myClass("hello, world");
}
return 0;
}
And now let's put the book down and do it the right way:
Pros:
Optimal efficiency
Correct type limitations
DRY
Cons:
None
-
#include <iostream>
#include <string>
#include <type_traits>
class MyClass
{
public:
template <class T, std::enable_if_t<std::is_constructible<std::string, T>::value>* = nullptr>
MyClass(T&& data)
: _data(std::forward<T>(data))
{
std::cout << "MyClass universal reference template c'tor" << std::endl;
}
private:
std::string _data;
};
int main()
{
using namespace std::string_literals;
auto a = MyClass("hello"s);
auto b = MyClass("world");
const auto s = "Hello, World"s;
auto s2 = "Hello, World";
auto c = MyClass(s);
auto d = MyClass(s2);
// won't compile
// auto e = MyClass(10);
}

segfault when accessing static std::map

I'm trying to refactor a rather complicated piece of code and run into segfaults during loading the library. This is a minimal example of what I could single out to be the source of the segfault:
#include <iostream>
#include <string>
#include <map>
class Manager {
public:
class Action{
};
static bool registerAction(const Action* a, const char* name);
};
namespace Actions {
class ExampleAction : public Manager::Action {
};
namespace {
static bool available = Manager::registerAction(new ExampleAction(),"ExampleAction");
}
}
namespace {
typedef std::map<const std::string,const Manager::Action*> ActionList;
static ActionList sActions;
}
bool Manager::registerAction(const Action* a, const char* name){
std::cout << "attempting to register action " << a << " as " << name << std::endl;
sActions[name] = a;
std::cout << "done" << std::endl;
return true;
}
int main(){
std::cout << "hello!" << std::endl;
for(auto it:sActions){
std::cout << it.first << std::endl;
}
std::cout << "world!" << std::endl;
return 0;
}
It compiles fine with g++ 4.8.4 using the --std=c++11 flag, but upon execution, this happens:
attempting to register action 0x1ebe010 as ExampleAction
Segmentation fault (core dumped)
The line attempting to register comes first, which is of course expected, but the line assigning the value to the static map instance causes the crash, and I don't understand the reason. I'm probably being stupid here, but still - any suggestions on how to fix this?

C++11 rvalue object field

Can I have class/struct with rvalue field in c++11?
Like this one:
template<typename T>
struct RvalueTest{
RvalueTest(T&& value) : value( std::forward<T>(value) ){}
T&& value;
};
Because in the following test:
class Widget {
public:
Widget(){std::cout << "Widget ctor " << std::endl; }
Widget(int h) : h(h){std::cout << "Widget ctor param " << std::endl; }
Widget(const Widget&) { std::cout << "Widget copy ctor " << std::endl; }
Widget(Widget&&) { std::cout << "Widget move ctor " << std::endl; } // added this
template<typename T>
Widget(const T&) { std::cout << "Generalized Widget copy ctor " << std::endl; }
template<typename T>
Widget(T&&) { std::cout << "Universal Widget ctor " << std::endl; }
int h;
};
RvalueTest<Widget> r(Widget(12));
std::cout << r.value.h;
I got some trash value at output (with -O2):
http://coliru.stacked-crooked.com/a/7d7bada1dacf5352
Widget ctor param
4203470
And right value with -O0:
http://coliru.stacked-crooked.com/a/f29a8469ec179046
Widget ctor param
12
WHY???
P.S. What I try to achive is a single ctor call, without any additional move/copy constructors.
UPDATED
It compiles ok with clang http://coliru.stacked-crooked.com/a/6a92105f5f85b943
GCC bug? Or it works as it should ?
The problem is not specific to rvalue references. You will see the same odd behaviour, if you replace T&& by const T&.
template<typename T>
struct ReferenceTest{
ReferenceTest(const T& value) : value(value){}
const T& value;
};
The problem is, that you are storing a reference to a temporary object. The temporary object is automatically destroyed at the end of the statement it was created, but you try to access it later via the reference.
RvalueTest<Widget> r(Widget(12)); // pass reference to temporary object to constructor
std::cout << r.value.h; // invalid reference
It is possible to use rvalue references as member variables. However, you have to be careful if doing so. An example from the standard library is std::forward_as_tuple.
auto t = std::forward_as_tuple(42);
// t has type std::tuple<int&&>
Regarding the question how to avoid the copy or move construction: Don't use rvalue reference member variables. Here are two approaches, you can use instead:
std::unique_ptr: If copying or moving a Widget is too expensive, you can use a smart pointer:
template <typename T>
struct Test
{
std::unique_ptr<T> _value;
explicit Test(std::unique_ptr<T> value) : _value{std::move(value)} { }
};
Test<Widget> t{std::make_unique<Widget>(12)};
std::cout << t._value->h;
The second approach creates the Widget in-place. That's what the different emplace functions of the standard containers do, e.g. std::vector::emplace_back.
template <typename T>
struct Test
{
T _value;
template <typename ...Args>
explicit Test(Args&&... args) : _value{std::forward<Args>(args)...} { }
};
Test<Widget> t{12};
std::cout << t._value.h;

Clang issue: Detecting constexpr function pointer with SFINAE

Based on the answer in Detecting constexpr with SFINAE I'm trying to use SFINAE to check if a 'constexpr' is present in my class.
The problem is that the constexpr is a function pointer:
#include <type_traits>
#include <iostream>
typedef int (*ptr_t)();
int bar() { return 9; }
struct Foo {
static constexpr ptr_t ptr = &bar;
};
namespace detail {
template <ptr_t>
struct sfinae_true : std::true_type {};
template <class T>
sfinae_true<T::ptr> check(int);
// Commented out to see why clang was not evaluating to true. This should only be
// a comment when debugging!
// template <class>
// std::false_type check(...);
} // detail::
template <class T>
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
int main(int argc, char *argv[]) {
std::cout << has_constexpr_f<Foo>::value << std::endl;
return 0;
}
It seems to work fine using gcc, but clang complains:
test.cxx:23:39: error: no matching function for call to 'check'
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
^~~~~~~~~~~~~~~~
test.cxx:26:22: note: in instantiation of template class 'has_constexpr_f<Foo>' requested here
std::cout << has_constexpr_f<Foo>::value << std::endl;
^
test.cxx:16:25: note: candidate template ignored: substitution failure [with T = Foo]: non-type template argument for template parameter of pointer type 'ptr_t' (aka 'int (*)()') must have its address taken
sfinae_true<T::ptr> check(int);
~ ^
1 error generated.
Q1: Can anyone suggest a way of doing this which works both for Clang and GCC?
Q2: Is this a bug in gcc, clang or is this left undefined in the c++ standard?
That's not a bug in clang, but an unfortunate restriction of arguments for non-type template parameters of pointer type (see pointer as non-type template argument). Essentially, you can only use arguments of the form &something: [temp.arg.nontype]/1 (from n3797)
[if the template-parameter is a pointer, its argument can be] a constant expression (5.19) that designates the address of a
complete object with static storage duration and external or
internal linkage or a function with external or internal linkage,
including function templates and function template-ids but excluding
non-static class members, expressed (ignoring parentheses) as &
id-expression, where the id-expression is the name of an object or
function, except that the & may be omitted if the name refers to a
function or array and shall be omitted if the corresponding
template-parameter is a reference; or [..]
[emphasis mine]
You can however, use a function pointer in a constant expression that has a non-pointer type, for example a boolean expression such as
T::ptr != nullptr
This works under clang++3.5 and g++4.8.2:
#include <type_traits>
#include <iostream>
typedef int (*ptr_t)();
int bar() { return 9; }
struct Foo0 {
static constexpr ptr_t ptr = &bar;
};
struct Foo1 {
static const ptr_t ptr;
};
ptr_t const Foo1::ptr = &bar;
struct Foo2 {
static const ptr_t ptr;
};
//ptr_t const Foo2::ptr = nullptr;
namespace detail
{
template <bool>
struct sfinae_true : std::true_type {};
template <class T>
sfinae_true<(T::ptr != nullptr)> check(int);
// the result of the comparison does not care
template <class>
std::false_type check(...);
} // detail::
template <class T>
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
int main(int argc, char *argv[]) {
std::cout << std::boolalpha << has_constexpr_f<Foo0>::value << std::endl;
std::cout << std::boolalpha << has_constexpr_f<Foo1>::value << std::endl;
std::cout << std::boolalpha << has_constexpr_f<Foo2>::value << std::endl;
return 0;
}
Note there's a difference between clang++ and g++ for the second output (Foo1): g++ says true, clang++ says false.

Resources