Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这算是SFINAE吗?_C++_C++11_Sfinae - Fatal编程技术网

C++ 这算是SFINAE吗?

C++ 这算是SFINAE吗?,c++,c++11,sfinae,C++,C++11,Sfinae,大约一周前,我问了一个问题,询问如何仅在类模板所采用的类型具有特定的成员函数时,才能够简单地实例化类模板。在我的回答中,我得到了一个复杂的解决方案。但后来我试着自己去做。我只是想知道这是否足以找出一个给定类型T是否有一个名为f的无效函数,该函数取0个参数 #include <type_traits> #include <utility> template <typename T, typename = void> struct has_f : std::fa

大约一周前,我问了一个问题,询问如何仅在类模板所采用的类型具有特定的成员函数时,才能够简单地实例化类模板。在我的回答中,我得到了一个复杂的解决方案。但后来我试着自己去做。我只是想知道这是否足以找出一个给定类型
T
是否有一个名为
f
的无效函数,该函数取0个参数

#include <type_traits>
#include <utility>

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

template <typename T>
struct has_f<
    T,
    decltype(std::declval<T>().f(), void())> : std::true_type { };

template <typename T, typename = typename std::enable_if<has_f<T>::value>::type>
struct A { };

struct B
{
    void f();
};

struct C { };

template class A<B>; // compiles
template class A<C>; // error: no type named ‘type’ 
                     // in ‘struct std::enable_if<false, void>’
#包括
#包括
模板
结构有f:std::false\u类型{};
模板
结构有<
T
decltype(std::declval().f(),void())>:std::true_type{};
模板
结构A{};
结构B
{
无效f();
};
结构C{};
模板类别A;//汇编
模板类别A;//错误:没有名为“type”的类型
//在“struct std::enable_if”中

如果是这样,为什么其他答案在

中如此复杂?是的,您已经用最简单、最惯用的C++11 SFINAE风格解决了这个问题

请注意,您没有检查返回类型是否为
void
,是否为非静态成员,也没有检查是否没有参数
f
可以简单地无参数调用。它甚至可能是一个函子

要检查返回
void
的空成员非静态函数,请使用

template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) >( &T::f ) )) >
    : std::true_type {};

template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) const >( &T::f ) )) >
    : std::true_type {};
模板
结构具有_f(&T::f))>
:std::true_type{};
模板
结构具有_f(&T::f))>
:std::true_type{};

是的,这是SFINAE,是的,这是正确的。至于为什么其他答案更复杂。。。很难说。为了澄清
本身依赖于SFINAE,
A
不依赖于SFINAE。可能的情况是,某些编译器(cough MSVC2012)对SFINAE的支持有点糟糕,因此这种复杂性可能是拥有更具可移植性SFINAE的变通方法。另外,
std::declval().f()
std::declval().f()
(或者是
std::declval().f()
?)在C++1y中可能是不同的,因为对
这个
特性的右值引用。所以我使用
std::result\u来检查返回类型是否为void?@MemyselfandI这是一种方法,您也可以使用
decltype
std::result_of
做了一个奇怪的动作来支持
std::bind
std::function
使用的调用概念。有关一次检查多个条件的快速方法,请参见我的编辑。在任何情况下,您也需要
std::is_same
。我想您的意思是
std::is_same::value
(移动的右括号),以及类似的,对于下面的行。@MemyselfandI
std::result\u of
的标准不要求对SFINAE友好。然而,最近足够多的实现确实试图做到这一点(否则它会使trait难以使用)。@LucDanton批准的C++11草案并不要求它,但不久之后它作为C++1y特性被添加。无论哪种方式,它都不会真正为自己的钱运行
decltype
,除非您使用指向INVOKE的成员案例的特殊指针。