给出以下代码,
@p_id
主要收益是什么? GCC和MSVC表示1,C叫0。
答案 0 :(得分:9)
我认为Clang就在这里。 [class.qual]中的规则是:
在不忽略函数名称且嵌套名称说明符提名类
C
的查找中:
- 如果在
C
中查找的 nested-name-specifier 之后指定的名称是{{1 }}([class])或- [...这里无关...]
该名称被认为是为类
C
的构造函数命名。 [注:例如,构造函数不是精化类型说明符中可接受的查找结果,因此不会使用构造函数代替注入的 -class-name 。 -[注释]] 这样的构造函数名称只能在命名构造函数的声明的 declarator-id 中使用,也可以在using-声明中使用。 [示例:C
-举个例子]
struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba; // object of type A
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A
与typename C::T
一样,它的查找中不忽略函数名称(A::A
不会导致函数名称被忽略)。因此,在typename
中,当typename C::T
为C
时,名称T
被认为是构造函数的名称。由于它不是类型名,因此应该出现替换失败并回退到主模板的情况。
提起86818。
答案 1 :(得分:4)
为完成Barry的回答,typename
仅对编译器说,以下名称是在模板实例化之前执行的分析的类型。实例化后,将执行名称查找,就好像类型名不存在一样,Django rest framework nested self-referential objects:
通常的合格名称查找用于查找合格ID ,即使存在typename 。
所以Clang是正确的。为了获得一致的编译器行为,您可以使用[temp.res]/4 struct C::T
代替typename C::T
:
template <class> using void_t = void;
template <class C, class = void> struct X { enum { v = 0 }; };
template <class C> struct X<C, void_t<struct C::T> > { enum { v = 1 }; };
struct T { };
int main() { return X<T>::v; }