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

Ambiguous call in custom member detector

本文关键字:模糊 调用 成员 检测器 自定义      更新时间:2023-10-16

我在自己的成员检测器实现中工作,以提高我的编程技能。下面的代码在g++中可以很好地编译,但是clang++拒绝该代码,错误是:

main.cpp:19:17:注意:候选函数[with U = has_member::HasIt]

static char check(decltype(U::i)*);

main.cpp:22:16:注:候选函数[with U =has_member:军队):

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;
}

此处为实例

问题是:代码有效吗?如果是,为什么g++接受它?

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

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

nullptr可转换为两种指针类型,两种转换都不优于另一种,两个候选对象都是函数模板。但前者比后者更专业,所以应该优先考虑。这是一个clang bug。

一个对两个编译器都有效的简单解决方法是将第二个重载改为:

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;