7

C++11 標準のドラフト N3337 では、[namespace.udecl]

using 宣言は、using 宣言が現れる宣言領域に名前を導入します。

すべての using 宣言は宣言とメンバー宣言であるため、クラス定義で使用できます。

メンバー宣言として使用される using 宣言では、nested-name-specifier は、定義されているクラスの基本クラスに名前を付けるものとします。

これは通常、次の例のように、基本クラス内で保護された 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>: 「エラー: 非型で使用される 'typename' キーワード」。

typedef のコメントを外すと、B最初のインスタンス化の前に解析するときにエラーが発生します。Typeこれは、コンパイラが依存型名として扱わないためだと思います。

の最後の段落は[namespace.udecl]、using 宣言が依存する名前を指定する可能性があること、およびtypename導入された名前のさらなる使用法を明確にするためにキーワードを使用する必要があることを示唆しています。

using-declaration がキーワード typename を使用し、従属名 (14.6.2) を指定する場合、using-declaration によって導入された名前は typedef-name として扱われます。

私の読書は、それが従属名であることを[temp.dep]示唆しています。A<T>::Type論理的には、using 宣言によって導入された名前も依存する必要がありますが[temp.dep]、依存する using 宣言の場合については明示的に言及していません。何か不足していますか?

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;
};

実際、2番目の例では、書くtypedefためIntTypeに同じことをしなければなりません。

于 2014-11-26T21:10:53.970 に答える