C 11标准的N3337草案于 [namespace.udecl]
中声明
using声明在声明区域中引入了一个名称,其中出现using声明 . 每个using声明都是声明和成员声明,因此可以在类定义中使用 . 在用作成员声明的using声明中,嵌套名称说明符应命名要定义的类的基类 .
这通常用于在派生类的基类public中创建受保护的typedef,如下例所示,它在最新版本的Clang中成功编译:
struct A
{
protected:
typedef int Type;
};
struct B : A
{
using A::Type;
};
B::Type x;
using声明可以引用模板类 . 这编译:
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>
:"error: 'typename' keyword used on a non-type"时导致错误 .
取消注释typedef会在首次实例化之前解析 B
时导致错误 . 我猜这是因为编译器不会将 Type
视为依赖类型名称 .
[namespace.udecl]
的最后一段建议使用声明可以指定依赖名称,并且必须使用 typename
关键字以消除对引入的名称的进一步使用的歧义:
如果using声明使用关键字typename并指定依赖名称(14.6.2),则using声明引入的名称将被视为typedef-name
我对 [temp.dep]
的解读表明 A<T>::Type
是一个从属名称 . 从逻辑上讲,using-declaration引入的名称也应该是依赖的,但 [temp.dep]
没有明确提到依赖using声明的情况 . 我错过了什么吗?
2 回答
问题是
Type
不是类,而是类模板 . 您可以执行以下操作(这样您告诉编译器Type
是B
范围内的类模板):实际上,在你的第二个例子中为
typedef
写typedef
你必须做同样的事情 .是的,具有依赖qualified-id的类成员using声明引入了依赖名称 .
如果引入的名称是依赖的,它仍然是依赖的 - 我找不到任何其他建议 .
但是,using-declaration语法不提供指定依赖名称是模板的方法 . 对
B
中的从属名称Type
的后续引用可能会也可能不会引用模板,因此无法解析Type<int>
.以下示例演示了依赖的using声明的有效用法 .