SFINAE检测静态方法

SFINAE to detect static method

我正在尝试实现一种机制来检测所提供的 class 是否包含某些静态方法。这是非常简单的代码,但我不明白为什么 decltype() 对于 EnableIfHasFooMethod class:

的专业化没有按预期工作
#include <iostream>

struct A {
    static int Foo() { return 0; }
};

template <class T, class = void>
struct EnableIfHasFooMethod {};

template <class T>
struct EnableIfHasFooMethod<T, decltype(T::Foo)> {
    typedef void type;
};

template <class T, class = void>
struct HasFooMethod {
    static const bool value = false;
};

template <class T>
struct HasFooMethod<T, typename EnableIfHasFooMethod<T>::type> {
    static const bool value = true;
};

int main() {
    std::cout << HasFooMethod<A>::value << std::endl;
    return 0;
}

输出为 0,但应为 1

您忘记添加void()

template <class T>
struct EnableIfHasFooMethod<T, decltype(T::Foo, void())> { /* ... */ };
// ...........................................^^^^^^^^

您需要匹配

中的第二种类型 (void)
// ........................vvvv
template <class T, class = void>
struct EnableIfHasFooMethod {};

所以你的 decltype() 必须 return void 当且仅当 T.[=31= 中有一个 Foo() 成员]

你不能写

decltype( T::Foo )

因为,在这种情况下,decltype() return 成员的类型 Foo(如果存在)不能是 void.

你不会写

decltype( void() )

因为,在这种情况下,decltype() return 曾经 void,但如果有 Foo T

中的成员

所以解决方案是

decltype( T::Foo , void() )

所以 SFINAE 可以工作,替换失败,如果没有 Foo 成员,returning void 如果有 Foo.

因为这可能仍然引起人们的兴趣,所以让我说 EnableIfHasFooMethod 是多余的(如果我没记错的话)。这应该同样有效:

template <class T, class = void>
struct HasFooMethod: public std::false_type {};
template <class T>
struct HasFooMethod<T, std::void_t<decltype(T::Foo)>>: public std::true_type {};