wil*_*llj 6 c++ templates language-lawyer
在下面的示例中,A
有一个成员typedef Instantiate
导致实例化B<A>
.
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A<int>'
};
template<typename T>
struct A
{
typedef int Before;
typedef typename B<A>::After Instantiate;
typedef int After;
};
template struct A<int>; // instantiate A<int>
Run Code Online (Sandbox Code Playgroud)
我尝试过的所有编译器都报告说,虽然A::Before
可见但A::After
并非如此.这种行为是否符合标准?如果是这样,标准在哪里指定A
在实例化期间哪些名称应该可见B<A>
?
如果依赖名称"在模板实例化时查找",那么在由模板参数限定的名称场景中,这意味着什么T::After
?
编辑:请注意,当A不是模板时,会发生相同的行为:
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A'
};
struct A
{
typedef int Before;
typedef B<A>::After Instantiate;
typedef int After;
};
Run Code Online (Sandbox Code Playgroud)
..和G ++接受以下内容,但Clang没有:
template<typename T>
struct B
{
static const int value = 0;
static const int i = T::value; // clang error: not a constant expression
};
struct A
{
static const int value = B<A>::value;
};
Run Code Online (Sandbox Code Playgroud)
编辑:经过一些C++ 03标准的阅读:
[temp.dep.type]如果类型是模板参数,则该类型是相关的
因此T
是依赖的.
[temp.res]在查找模板定义中使用的名称声明时,通常的查找规则用于非依赖名称.依赖于模板参数的名称查找被推迟,直到知道实际模板参数.
因此,查询T::After
被推迟,直到T
知道参数为止.
[temp.inst]除非已显式实例化类模板特化,否则在需要完全定义的对象类型的上下文中引用特化时,将隐式实例化类模板特化.
因此声明A<int>::Instantiate
需要实例化B<A>
(因为它在嵌套名称说明符中使用.)
A<int>::After
在声明时是不可见的A<int>::Instantiate
,因此编译器的行为是有意义的 - 但我没有在C++ 03中看到任何明确描述此行为的内容.最接近的是这个有点模糊的段落:
[temp.dep.res]在解析依赖名称时,会考虑以下来源的名称:
- 在模板定义点可见的声明.
typename T::Before
规范中没有明确说明是否有效。它是缺陷报告的主题(因为可以非常合理地阅读该标准来禁止它):http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287。
是否typename T::After
无效也可以很合理地被规范解读为正确,实际上它很有道理(前面提到的 DR 仍然保持它的格式错误)。因为您有一个类的实例化A<Foo>
,它在尚未声明A<Bar>
成员的期间引用了另一个类,并且这会引用回. 在非模板的情况下,这也是格式不正确的(尝试暂时“忘记”您正在处理模板:当然,查找是在模板完全解析之后完成的,而不是在它的特定实例化之后完成的已完全创建。并且它的实例化实际上将进行引用!)。Baz
A<Foo>::Bar
B<A>::After
A
struct A {
typedef int Foo;
typedef A::Foo Bar; // valid
typedef A::Baz Lulz; // *not* valid
typedef int Baz;
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
705 次 |
最近记录: |