SFINAE检测静态方法

时间:2017-10-08 23:03:47

标签: c++ c++11 templates template-specialization sfinae

我正在尝试实现一种机制来检测提供的类是否包含某些静态方法。这是非常简单的代码,但我无法理解为什么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

2 个答案:

答案 0 :(得分:3)

您忘了添加void()

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

您需要匹配

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

因此decltype()必须返回void iff(当且仅当如此)Foo()中有T成员。

你不能写

decltype( T::Foo )

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

你不能写

decltype( void() )

因为,在这种情况下,decltype()会返回永远 void,但如果Foo中有T成员,则需要{} / p>

所以解决方案是

decltype( T::Foo , void() )

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

答案 1 :(得分:0)

因为这可能仍然使人们感兴趣,所以让我指出#include "bmp.c" int main(){ FILE *BMP_file = fopen("./assets/lenna.bmp", "rb"); struct bmp_header* Header; memset(&Header, 0, sizeof(struct bmp_header)); Header = read_bmp_header(BMP_file); printf("%x\n", Header->type); fclose(BMP_file); return 0; } 是多余的(如果我没有记错的话)。这应该同样有效:

EnableIfHasFooMethod