【问题标题】:SFINAE to detect static methodSFINAE检测静态方法
【发布时间】:2017-10-08 23:03:46
【问题描述】:

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

【问题讨论】:

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


    【解决方案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() 返回成员 Foo(如果存在)的类型,它不能是 void

    你不会写

    decltype( void() )
    

    因为,在这种情况下,decltype() 返回 ever void,但如果 T 中有 Foo 成员,则您想要它

    所以解决办法是

    decltype( T::Foo , void() )
    

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

    【讨论】:

    • 我忘了专业化应该是针对默认模板参数的。谢谢!
    • 喜欢逗号操作符
    • @quetzalcoatl - 我也是。
    • void_t&lt;decltype(T::Foo)&gt; ,这就是它的用途。
    【解决方案2】:

    由于这可能仍然引起人们的兴趣,让我指出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 {};
    

    【讨论】:

    • 但这不会区分静态函数Foo()和成员变量Foo
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多