C++11 _enum是否导致SFINAE应用程序的错误行为?

C++11 _enum是否导致SFINAE应用程序的错误行为?,c++11,sfinae,typetraits,decltype,C++11,Sfinae,Typetraits,Decltype,我一直在研究应用于“has_member”类型结构的SFINAE,如前所述 所以我尝试使用c++11的一些特性来简化这些解决方案。在检查枚举是否存在时遇到一些问题,但我似乎无法在此处找到我的逻辑错误。代码是: #include<iostream> template<typename T > struct has_enum_name { private: // ***** this is the line that isn't working ***** // I

我一直在研究应用于“has_member”类型结构的SFINAE,如前所述

所以我尝试使用c++11的一些特性来简化这些解决方案。在检查枚举是否存在时遇到一些问题,但我似乎无法在此处找到我的逻辑错误。代码是:

#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;
}
#包括
模板
结构具有_enum _名称
{
私人:
//******这条线坏了*****
//如果你有一个枚举“name”,那么我希望is_enum返回true…
//然后我希望enable_if::type是std::true_type…等等。这不是实际情况。
模板静态自动测试(int)->decltype(
std::enable_if::value,std::true_type>::type();
模板静态自动测试(…)->std::false_类型;
公众:
静态constexpr布尔值=
!(std::is_same::value);
静态constexpr bool是_enum()
{
返回std::is_enum::value;
}
};
模板
结构具有\u枚举\u名称\u 2
{
私人:
模板静态自动测试(int)->decltype(
std::enable_if::type());
模板静态自动测试(…)->std::false_类型;
公众:
静态constexpr布尔值=
!(std::is_same::value);
};
结构Foo
{
枚举类名
{
列举1,
枚举2
};
};
int main()
{

std::cout当您遇到这样的问题时,让编译器帮助您。删除
(…)
重载以强制执行编译错误,并查看GCC告诉您的信息:

test.cc:在“constexpr const bool has_enum_name::value”的实例化中:
测试。cc:51:71:此处需要
test.cc:18:33:错误:调用“has_enum_name::test(int)”时没有匹配的函数
!(std::is_same::value);
^
考试。抄送:18:33:注:考生为:
test.cc:12:36:注意:模板静态decltype(std::enable_if::type())具有\U enum\U name::test(int)[带U=U;T=Foo]
模板静态自动测试(int)->decltype(
^
test.cc:12:36:注意:模板参数扣除/替换失败:
test.cc:替换“模板静态decltype(std::enable_if::type())具有_enum_name::test(int)[带U=Foo]”:
test.cc:18:33:来自“constexpr const bool has_enum_name::value”的必填项
测试。cc:51:71:此处需要
test.cc:13:83:错误:依赖名称“std::enable_if::type”被解析为非类型,但实例化会生成一个类型
std::enable_if::value,std::true_type>::type();
^
test.cc:13:83:注意:如果某个类型的意思是
这正是问题所在:您只是忘记添加
typename
T::type()
如果
type
是非类型,那么它可能是有效的:它可能只是一个函数调用。编译器就是这样解析它的

顺便说一句,
decltype(typename T::type())
似乎有些毫无意义,除非您特别尝试检查该类型是否是默认可构造的,而这不是您在这里要做的。您可以直接使用
typename T::type
,如下所示:

template<typename U> static auto test(int) ->
  typename std::enable_if<std::is_enum<typename U::name>::value, std::true_type>::type;

您好,谢谢您关于删除(…)的提示。我想真正的问题应该是“如何调试SFINAE?”,这当然有帮助!我仍然困惑的是为什么“std::enable_if::type”不需要typename,而“std::enable_if::type;”是。@doc07b5
std::enable_if::type
不依赖于模板参数,因此编译器在解析模板时可以看到它是一个类型。
std::enable_if::type
依赖于模板参数
U
,因此您需要告诉编译器,您希望它总是生成一个类型名为
typename的类型
关键字。
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(int) ->
  typename std::enable_if<std::is_enum<typename U::name>::value, std::true_type>::type;
static constexpr bool value = decltype(test<T>(0))::value;