7

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]没有明确提及依赖使用声明的情况。我错过了什么吗?

4

2 回答 2

2

问题是它Type不是一个类,而是一个类模板。您可以执行以下操作(这样您就可以告诉编译器这Type是 范围内的类模板B):

template<typename T>
struct B : A<T>
{
    using A<T>::Type;
    typedef typename B::template Type<int> IntType;
};

实际上,在您的第二个示例中,为了typedef为您写作,IntType您必须这样做。

于 2014-11-26T21:10:53.970 回答
0

是的,具有依赖限定 ID 的类成员 using-declaration 引入了依赖名称。

[命名空间.udecl]

using-declaration 将名称引入到 using-declaration 出现的声明性区域中。

如果引入的名称是依赖的,它会保持依赖——否则我找不到任何建议。

但是,using-declaration 语法没有提供一种方法来指定从属名称是一个模板。Type对依赖名称的后续引用B可能会或可能不会引用模板,因此Type<int>无法解析。

以下示例演示了依赖 using 声明的有效用法。

template<typename T>
struct A
{
protected:
    struct Type
    {
        typedef int M;
    };
};


template<typename T>
struct B : A<T>
{
    using typename A<T>::Type;
    typedef typename Type::M Type2;
};

B<int>::Type2 x;
于 2014-11-26T21:26:53.007 回答