C++11 标准草案 N3337 在[namespace.udecl]
using-declaration 将名称引入到 using-declaration 出现的声明性区域中。
每个 using-declaration 都是一个声明和一个成员声明,因此可以在类定义中使用。
在用作成员声明的 using-declaration 中,nested-name-specifier 应命名正在定义的类的基类。
这通常用于在派生类中使基类中的受保护类型定义为公共,如下例所示,该示例在最新版本的 Clang 中成功编译:
struct A
{
protected:
typedef int Type;
};
struct B : A
{
using A::Type;
};
B::Type x;
using-declaration 可以引用模板类。这编译:
struct A
{
protected:
template<typename T>
struct Type
{
};
};
struct B : A
{
using A::Type;
};
B::Type<int> x;
也可以在依赖基类中引用模板。以下编译成功(带有 typedef 注释。)
template<typename T>
struct A
{
protected:
template<typename U>
struct Type
{
};
};
template<typename T>
struct B : A<T>
{
using /* typename */ A<T>::Type; // A<T> is dependent, typename required?
// typedef Type<int> IntType; // error: unknown type name 'Type'
};
B<int>::Type<int> x;
实例化时取消注释typename
会导致错误B<int>
:“错误:在非类型上使用'typename'关键字”。
B
在第一次实例化之前解析 typedef 时,取消注释会导致错误。我猜这是因为编译器不将Type
其视为依赖类型名称。
最后一段[namespace.udecl]
建议 using-declarations 可以指定依赖名称,并且typename
必须使用关键字来消除对引入名称的进一步使用的歧义:
如果 using-declaration 使用关键字 typename 并指定依赖名称 (14.6.2),则 using-declaration 引入的名称被视为 typedef-name
我的阅读[temp.dep]
表明这A<T>::Type
是一个从属名称。从逻辑上讲,使用声明引入的名称也应该是依赖的,但[temp.dep]
没有明确提及依赖使用声明的情况。我错过了什么吗?