20

次のスニペットをコンパイルするとg++

template<class T>
class A
{};

template<class T>
class B
{
    public:
        typedef A<T> A;
};

コンパイラが教えてくれる

error: declaration of ‘typedef class A<T> B<T>::A’
error: changes meaning of ‘A’ from ‘class A<T>’

一方、に変更するtypedefと、

typedef ::A<T> A;

すべてが正常にコンパイルされg++ます。Clang++ 3.1 はどちらの方法も気にしません。

なぜこうなった?そして、2番目の行動基準はありますか?

4

2 に答える 2

13

g++ は正しく、標準に準拠しています。[3.3.7/1] より:

クラス S で使用される名前 N は、そのコンテキスト内で同じ宣言を参照し、S の完全なスコープで再評価される場合に参照する必要があります。この規則違反の診断は必要ありません。

以前は typedef をA参照していましたが、typedef::Aを使用するAことで、禁止されている typedef を参照するようになりました。ただし、no diagnostic is requiredなのでclangも規格に準拠しています。

jogojapan のコメントは、このルールの理由を説明しています。コードに次の変更を加えます。

template<class T>
class A
{};

template<class T>
class B
{
    public:
        A a; // <-- What "A" is this referring to?
        typedef     A<T>            A;
};

クラススコープがどのように機能するかにより、A a;あいまいになります。

于 2012-08-29T23:07:21.813 に答える