C++ 传递0而不是1时sfinae不明确调用

C++ 传递0而不是1时sfinae不明确调用,c++,c++11,sfinae,C++,C++11,Sfinae,相关代码: #include <iostream> #include <type_traits> template<template<typename...> class C, typename... T> struct is_valid_instantiation_impl { // Default constructor template<template<typename...> class D> sta

相关代码:

#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
仍然是一个int(GCC 4.8.2似乎同意我的观点,但也不会编译它):

编辑:

请注意,我不是问如何解决这种歧义,而是问为什么我使用
0
而不是
1
时会出现歧义。
有关显示错误的完整代码,请参阅。

我不知道您的
C
D
是什么,但基本上您有两个重载:

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

test(nullptr, 0);
nullptr
匹配第一个参数,而
0
匹配第二个参数。这两种重载都是可行的,而且两者都不是比另一种更好的选择。因此:

错误:重载的
'test(std::nullptr\u t,int)
调用不明确

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

空指针常量是值为零的整数文本或类型为
std::nullptr\t
的prvalue。空指针常量可以转换为指针类型;结果是该类型的空指针值 和对象指针或函数指针类型的所有其他值不同

在一些C++编译器中(大多数?我不确定),NulLPTR定义为0。如果您使用的是托管指针,那么nullptr和0的定义不同。但是对于本机指针,它们是一样的

因此,您的代码遇到了这个文本0,编译器突然不知道它应该是指针还是整数,因为从技术上讲,它可能是指针还是整数。而“1”在C++中定义为文本int,所以没有混淆。
不幸的是,除了强制转换之外,我看不到任何方法可以明确地告诉编译器0应该是什么意思。

您在问题中提出的内容可以使用
1
0
进行编译,即使在使用虚拟
tester
模板类对其进行实例化之后也是如此。请发布一些实际演示您所问问题的内容。如果使用type=decltype(test(nullptr,static_cast(0))替换为
?@hvd因为我认为这对于我的问题来说有点太多了,请看
0
是一个空指针常量,所以您面临一个问题,它可以转换为指针或其他整数类型。显然,
1
不会遇到这个问题,因为它不是。@0x499602D2这是我想要的答案。仍然在和的最新版本上编译。@0x499602D2如果添加
C()=delete它的工作原理是因为(x*,int)重载优于其他两个。“在一些C++编译器中(大多数,我不确定),Null pTR被定义为0”, NulLPTR < /C> >是一个类型值:<代码> STD::nulpprtt。整数类型的空指针常量(如
0
)可以转换为
std::nullptr\t
,但相反的方法不起作用
nullptr
不是
0
。要添加到@PiotrS'的注释中,您可能会想到
NULL
而不是
nullptr
NULL
是一个宏,它几乎总是扩展到
0
0L
,但OP使用的不是这个宏。
xxx: error: call of overloaded ‘test(std::nullptr_t, int)’ is ambiguous
static std::true_type test(X*, long);
static std::true_type test(Y*, int*);

test(nullptr, 0);