c++ - sfinae在传递 0而不是 1时不明确的调用

  显示原文与译文双语对照的内容
0 0

相关代码:


#include <iostream>
#include <type_traits>

template<template<typename...> class C, typename... T>
struct is_valid_instantiation_impl
{
//Default constructor
 template<template<typename...> class D>
 static std::true_type test(decltype(D<T...>{ })*, int);
//Copy constructor
 template<template<typename...> class D>
 static std::true_type test(decltype(D<T...>{ std::declval<const D<T...>&>() })*, long);
//Move constructor
 template<template<typename...> class D>
 static std::true_type test(decltype(D<T...>{ std::declval<D<T...>&&>() })*, int*);

 template<template<typename...> class D>
 static std::false_type test(...);

 using type = decltype(test<C>(nullptr, 1));
//^ this one
};

template<template<typename...> class C, typename... T>
struct is_valid_instantiation : is_valid_instantiation_impl<C, T...>::type { };

template<typename>
struct tester;

template<>
struct tester<int>
{
 tester(int);
};

int main(int argc, char** argv)
{
 std::cout <<"instantiable<int>:" <<is_valid_instantiation<tester, int>::value <<std::endl;
}

这个代码编译好,但是当我用一个 0 来替换那个 1 时( Clang 3.4 )


xxx: error: call to 'test' is ambiguous
 using type = decltype(test<C>(nullptr, 0));
 ^~~~~~~
xxx: note: in instantiation of template class 'is_valid_instantiation_impl<tester, int>' requested here
...

xxx: note: candidate function [with D = tester]
 static std::true_type test(decltype(D<T...>{ std::declval<const D<T...>&>() })*, long);
 ^
xxx: note: candidate function [with D = tester]
 static std::true_type test(decltype(D<T...>{ std::declval<D<T...>&&>() })*, int*);
 ^
xxx: note: candidate function [with D = tester]
 static std::false_type test(...);
 ^

为什么突然这个调用不明确? 据我所知 0 仍然是一个 int ( 和GCC似乎同意我,但我不会编译它。):


xxx: error: call of overloaded 'test(std::nullptr_t, int)' is ambiguous

编辑:

请注意我不要求如何解决这个模糊性,但是为什么我使用 0 而不是 1的模糊性。 有关完整代码的详细说明,请参阅这个实时示例。

时间: 原作者:

0 0

不知道你的CD 是什么,但基本上你有这两个重载:


static std::true_type test(X*, long);
static std::true_type test(Y*, int*);

test(nullptr, 0);

nullptr 匹配第一个参数,而 0 匹配第二个参数。 两个重载都是可行的,并且两者都不是更好的候选者。 因此:

错误:重载的'test(std::nullptr_t, int)' 调用不明确

0 可以通过 int* 传递的原因是,从 [conv.ptr]:

空指针常量是一个带有零值或者类型为 prvalue of的整数。 空指针常量可以转换为指针类型;结果是该类型的null指针,并且可以与对象指针或者函数指针类型的其他任何值区分开来。

原作者:
0 0

在某些 C++ 编译器中( 大多数? 我不确定,nullptr被定义为 0. 如果你使用托管指针,则nullptr和 0的定义方式不同。 但是对于本机指针,它们是相同的。

因这里,你的代码将击中这个文本 0,编译器突然不知道这是一个指针还是整数。 在 C++ 中定义" 1"为文本整型,所以没有混淆。

不幸的是,我没有看到任何方法,除了强制转换以显式告诉编译器 0应该是什么。

...