SFINAE检测静态方法

SFINAE to detect static method

本文关键字:静态方法 检测 SFINAE      更新时间:2023-10-16

我正在尝试实现一种机制来检测提供的类是否包含一些静态方法。这是非常简单的代码,但我不明白为什么decltype()不能按预期工作EnableIfHasFooMethod类的专业化:

#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()必须返回 void IFF(当且仅当)T中有Foo()成员。

你不能写

decltype( T::Foo )

因为,在这种情况下,decltype()返回无法void的成员类型Foo(如果存在)。

你不能写

decltype( void() )

因为,在这种情况下,decltype()返回void,但您希望它,如果有一个Foo成员在T

所以解决方案是

decltype( T::Foo , void() )

所以SFINAE可以工作,如果没有Foo成员,则替换失败,如果有Foo,则返回void

由于人们可能仍然对此感兴趣,因此让我指出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 {};