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 {};
我正在尝试实现一种机制来检测所提供的 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 {};