I have been playing around with SFINAE applied to the "has_member" type of structs as described here.
So I was trying to use some of the features of c++11 to make these solutions simpler. Having some problems with checking for existence of an enum, but I can't seem to locate my logic error here. Code is:
#include<iostream>
template<typename T >
struct has_enum_name
{
private:
// ***** this is the line that isn't working *****
// If U has an enum "name", then I expect is_enum to return true…
// Then I expect enable_if<>::type to be std::true_type…etc. This isn't what happens.
template<typename U> static auto test(int) -> decltype(
std::enable_if<std::is_enum< typename U::name >::value, std::true_type>::type() );
template<typename U> static auto test(...) -> std::false_type;
public:
static constexpr bool value =
!(std::is_same<decltype(test<T>(0)),std::false_type>::value);
static constexpr bool is_enum()
{
return std::is_enum<typename T::name>::value;
}
};
template<typename T >
struct has_enum_name_2
{
private:
template<typename U> static auto test(int) -> decltype(
std::enable_if<true, std::true_type>::type() );
template<typename U> static auto test(...) -> std::false_type;
public:
static constexpr bool value =
!(std::is_same<decltype(test<T>(0)),std::false_type>::value);
};
struct Foo
{
enum class name
{
enum1,
enum2
};
};
int main()
{
std::cout<<"std::is_enum<Foo::name>::value = "<<std::is_enum<Foo::name>::value<<std::endl;
std::cout<<"has_enum_name<Foo>::value = "<<has_enum_name<Foo>::value<<std::endl;
std::cout<<"has_enum_name<Foo>::is_enum() = "<<has_enum_name<Foo>::is_enum()<<std::endl;
std::cout<<"has_enum_name_2<Foo>::value = "<<has_enum_name_2<Foo>::value<<std::endl;
}
Running this using gcc 4.9.2 gives
$ ./a.out
std::is_enum<Foo::name>::value = 1
has_enum_name<Foo>::value = 0
has_enum_name<Foo>::is_enum() = 1
has_enum_name_2<Foo>::value = 1
The first output line verifies that the std::is_enum works correctly for the Foo::name enum.
The second line outputs the results of struct constexpr "has_enum_name::value". I am just trying to use std::enable_if in conjunction with std::is_enum to make the decltype return something…in this case std::true_type(). As you can see, the output returns false…so the line:
template<typename U> static auto test(int) -> decltype(
std::enable_if<std::is_enum< typename U::name >::value, std::true_type>::type() );
isn't working out like i think it should. I think that is_enum should return true, which means that enable_if should return true_type, and decltype should return true_type().
Next output is just a check to see if std::is_enum<> is working correctly in the struct…it is.
Next output is just a copy of the "has_enum_name" struct, but I replaced the is_enum<> in the suspect line with a hard coded "true"…and it works correctly.
So for some reason, it appears that is_enum is not working returning true. Any ideas what I am doing wrong here?