C++ 标准:德克瓦尔<;T>;()、SFINAE和已删除的构造函数

C++ 标准:德克瓦尔<;T>;()、SFINAE和已删除的构造函数,c++,c++11,metaprogramming,sfinae,C++,C++11,Metaprogramming,Sfinae,在C++11中使用SFINAE进行方法检测时,我编写了以下运行示例: #include <type_traits> struct Foo { Foo();// = delete; Foo(int); void my_method(); }; template <typename T, typename ENABLE = void> struct Detect_My_Method : std::false_type { }; template &

在C++11中使用SFINAE进行方法检测时,我编写了以下运行示例:

#include <type_traits>

struct Foo
{
  Foo();// = delete;
  Foo(int);

  void my_method();
};

template <typename T, typename ENABLE = void>
struct Detect_My_Method 
   : std::false_type
{
};

template <typename T>
struct Detect_My_Method<T, decltype(T().my_method())> 
   : std::true_type
{
};

int main()
{
  static_assert(!Detect_My_Method<double>::value, "");
  static_assert(Detect_My_Method<Foo>::value, "");
}
示例为不再工作,我收到以下错误消息:

g++ -std=c++11 declVal.cpp 
declVal.cpp: In function ‘int main()’:
declVal.cpp:33:3: error: static assertion failed
   static_assert(Detect_My_Method<Foo>::value, "");
g++-std=c++11 declVal.cpp
declVal.cpp:在函数“int main()”中:
declVal.cpp:33:3:错误:静态断言失败
静态断言(检测我的方法::值“”;

问题:解释以及如何解决?

删除空构造函数时
构造:

decltype(Foo().my_method());
不再有效,编译器会立即投诉

error: use of deleted function ‘Foo::Foo()’
一个解决办法是使用

将任何类型T转换为引用类型,从而可以使用 decltype表达式中的成员函数,无需转到 通过构造函数

因此,取代:

template <typename T>
struct Detect_My_Method<T, decltype(T().my_method())> 
   : std::true_type
{
};
模板
struct Detect\u My\u方法
:std::true\u类型
{
};

模板
struct Detect\u My\u方法
:std::true\u类型
{
};
解决了这个问题

经验教训:

decltype(Foo().my_method());                // invalid
decltype(std::declval<Foo>().my_method());  // fine
decltype(Foo().my_method());//无效的
decltype(std::declval().my_method());//好的

不等效。

删除空构造函数时构造:

decltype(Foo().my_method());
不再有效,编译器会立即投诉

error: use of deleted function ‘Foo::Foo()’
一个解决办法是使用

将任何类型T转换为引用类型,从而可以使用 decltype表达式中的成员函数,无需转到 通过构造函数

因此,取代:

template <typename T>
struct Detect_My_Method<T, decltype(T().my_method())> 
   : std::true_type
{
};
模板
struct Detect\u My\u方法
:std::true\u类型
{
};

模板
struct Detect\u My\u方法
:std::true\u类型
{
};
解决了这个问题

经验教训:

decltype(Foo().my_method());                // invalid
decltype(std::declval<Foo>().my_method());  // fine
decltype(Foo().my_method());//无效的
decltype(std::declval().my_method());//好的

不等效。

此外,还有另一种定义测试的方法,既不需要指向对象的引用或指针,也不需要函数的特定签名:

template<class T>
typename std::is_member_function_pointer<decltype(&T::my_method)>::type test_member_function_my_method(int);

template<class T>
std::false_type test_member_function_my_method(...);

template<class T>
using has_member_function_my_method = decltype(test_member_function_my_method<T>(0));
模板
typename std::is_member_function_pointer::type test_member_function_my_method(int);
样板
std::false_类型测试_成员_函数_my_方法(…);
样板
使用has_member_function_my_method=decltype(test_member_function_my_method(0));
用法:

static_assert(!has_member_function_my_method<double>::value, "");
static_assert(has_member_function_my_method<Foo>::value, "");
static_assert(!has_member_function_my_method::value,”);
静态\u断言(具有\u成员\u函数\u我的\u方法::值“”);

此外,还有另一种定义测试的方法,既不需要指向对象的引用或指针,也不需要函数的特定签名:

template<class T>
typename std::is_member_function_pointer<decltype(&T::my_method)>::type test_member_function_my_method(int);

template<class T>
std::false_type test_member_function_my_method(...);

template<class T>
using has_member_function_my_method = decltype(test_member_function_my_method<T>(0));
模板
typename std::is_member_function_pointer::type test_member_function_my_method(int);
样板
std::false_类型测试_成员_函数_my_方法(…);
样板
使用has_member_function_my_method=decltype(test_member_function_my_method(0));
用法:

static_assert(!has_member_function_my_method<double>::value, "");
static_assert(has_member_function_my_method<Foo>::value, "");
static_assert(!has_member_function_my_method::value,”);
静态\u断言(具有\u成员\u函数\u我的\u方法::值“”);

这并不完全等同,因为
declval
方法可以检测函数对象。如果
T
具有成员变量
my\u method
运算符()
,它将检测到该变量有效。这可能是可取的,也可能不是可取的,也可能是你不在乎的。@Justin你说得对。它也不处理重载函数,因为这里不涉及调用参数。这并不完全等效,因为
declval
方法可以检测函数对象。如果
T
具有成员变量
my\u method
运算符()
,它将检测到该变量有效。这可能是可取的,也可能不是可取的,也可能是你不在乎的。@Justin你说得对。它也不处理重载函数,因为这里不涉及调用参数。