Clang和GCC中模糊基类转换之间行为的差异

时间:2014-10-05 21:44:37

标签: c++ c++11

以下打印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不正确,因为Dbase<n>有多次转换:ABC。 clang做的奇怪之处在于它似乎在其基本说明符列表中转换为 last 基类。

这是Clang的错误吗?我可以从标准中得到实际的措辞吗?

1 个答案:

答案 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;,但它传达了这一点。