以下打印GCC 4.9中的-1
,VC ++,但在Clang 3.5中打印2
:
template <int n>
struct base { static constexpr int value = n; };
struct A : base<0> { };
struct B : base<1> { };
struct C : base<2> { };
struct D : A, B, C { };
template <int n>
base<n> base_cast(base<n>);
template <typename T, typename B = decltype(base_cast(std::declval<T>()))>
std::integral_constant<int, B::value> f(int);
template <typename T>
std::integral_constant<int, -1> f(...);
constexpr int value = decltype(f<D>(0))::value;
int main()
{
std::cout << value << std::endl;
}
我说clang不正确,因为D
到base<n>
有多次转换:A
,B
和C
。 clang做的奇怪之处在于它似乎在其基本说明符列表中转换为 last 基类。
这是Clang的错误吗?我可以从标准中得到实际的措辞吗?
答案 0 :(得分:1)
标准中的第4条涉及标准转换:
4.2 [注意:具有给定类型的表达式将在多个上下文中隐式转换为其他类型:
- 用作初始化的源表达式(包括在函数调用中用作参数并用作return语句中的表达式)。被初始化的实体的类型(通常)是目的地类型。见8.5,8.5.3。
-end note]
4.3当且仅当声明T t = e时,表达式e可以隐式转换为类型T.形成良好,对于一些发明的临时变量t(8.5) 的
基于此,D可转化为碱基,&lt; 1&gt;。和基础&lt; 2&gt;。
base<0> b0 = D(); //compiles
base<1> b1 = D(); //compiles
base<2> b2 = D(); //compiles
由于有三种可能的转换,对base_cast的调用应该导致一个模糊的调用。
以下代码段:
template <int n>
void print_base(base<n>)
{
std::cout << n << std::endl;
}
...
print_base(D());
在gcc 4.7.2中给出以下错误:
error: no matching function for call to 'print_base(D)'
note: candidate is:
note: template<int n> void print_base(base<n>)
note: template argument deduction/substitution failed:
note: 'D' is an ambiguous base class of 'base<n>'
错误信息似乎有点偏离:&#39; D&#39;是一个模糊的&#34; base&#34; 类的基础&lt; n&gt;,但它传达了这一点。