4

さて、ここにコードがあります:

#include <sstream>

struct A {
    class Type {};
    template < typename Type >
    Type as( void ) {
        std::istringstream test;

        Type temp;
        test >> temp;

        return temp;
    }
};

正常にコンパイルされますが、まったく問題ありません。

さて、ここにほとんど同じコードがあります:

#include <sstream>

struct A {
    class Type {};
    template < typename Type >
    inline Type as(void);
};

template < typename Type >
Type A::as( void ) {
    std::istringstream test;

    Type temp;
    test >> temp;

    return temp;
}

ブーム、それはもうコンパイルされません。エラー :

t.cc:14:10: error: invalid operands to binary expression ('std::istringstream' (aka 'basic_istringstream<char>') and 'A::Type')
    test >> temp;
    ~~~~ ^  ~~~~

この動作をclangとgccで再現しました。

2番目のケースでコンパイラが間違ったタイプを使用しているのはなぜですか?(明確にするために:列挙との競合があることは知っていますが、私の理解から、それが本当の問題である場合、最初のコードもコンパイルに失敗するはずです)

4

1 に答える 1

3

A::as() のスコープは、temp の型修飾子として A::Type を使用します。これを確認する最も簡単な方法は、ネストされたクラス名を Type 以外の名前に変更することです。

より良い質問は、そもそもなぜそれが起こるのかです。これは、宣言のポイント、名前の検索、および名前の非表示に関連しており、すべて標準のセクション 3.3、3.4、および 14.6.4 で説明されています。これは非常に分厚いセクションのセットであり、絞り込む時間があれば、この問題に関連する特定の条項を投稿します。これまでのところ、私は 3.3.9-10 と 3.4 に頼っています

とにかく、クラス名を変更すると、テンプレート引数が struct宣言のスコープ外に一度解決されるようになります。後者は、そもそもなぜそれが起こるのかの鍵となります (とにかく、私は標準によって信じるようになります)。

struct A
{
    class TypeX {};
    template < typename Type >
    Type as(void);
};

template < typename Type >
inline Type A::as( void )
{
    std::istringstream test;
    Type temp;
    test >> temp;
    return temp;
}

この問題に関連する標準の間違ったセクションがある場合、この回答を通じてホットロッドを送るStackOverflowの十分な占有者がいると確信しています。

于 2012-11-17T07:40:03.717 に答える