自定义成员检测器中的模糊调用

时间:2015-09-30 17:34:35

标签: c++ templates c++11 typetraits

我正在自己实施一个成员探测器,以提高我的编程技巧。下面的代码用g ++很好地编译,但clang ++拒绝代码,错误是:

  

错误:调用'check'是不明确的main.cpp:19:17:注意:候选函数[有U = has_member :: HasIt]

     

静态字符检查(decltype(U :: i)*);

     

main.cpp:22:16:注意:候选函数[U =   has_member :: HasIt]

     

static int check(U *);

这是类的代码

template<typename T>
struct has_member 
{

    struct Fallback
    {
        int i;
    };

    struct HasIt : Fallback, T
    {};

    template<class U>
    static char check( decltype(U::i)* ); 

    template<typename U>
    static int check(U*);    

    static const bool value = sizeof(check<HasIt>( nullptr ) ) == sizeof(int);
};

class Test
{
public:

};

int main()
{
    auto v  = has_member<Test>::value;

    std::cout << std::boolalpha << v;
}

实例here

问题是:代码有效吗?如果这是g ++接受它的原因?

1 个答案:

答案 0 :(得分:1)

代码应该有效。我们有两个可行的候选人:

template <class U>
static char check( decltype(U::i)* ); // --> int*

template <class U>
static int check( U* ); // --> HasIt*

nullptr可以转换为两种指针类型,转换都不比另一种好,两种候选都是函数模板。但前者比后者更专业,因此应该首选。这是一个铿锵的错误。

适用于两个编译器的简单解决方法是将第二个重载更改为:

template<typename U>
static int check(...);   

由于优先于椭圆,所以仍然是后备选项,而不必依赖模板部分排序规则。

此外,由于我们在C ++ 11中,我们可以直接使用返回类型:

template<class U>
static std::false_type check( decltype(U::i)* ); 

template<typename U>
static std::true_type check(...);

using type = decltype(check<HasIt>(nullptr));
static constexpr bool value = type::value;