1

MSVC で問題なくコンパイルできるコードがいくつか与えられており、Xcode の Clang でコンパイルできるようにしようとしています。現在、次の typedef を使用してクラスが再定義されているという問題に遭遇しています。

typedef std::map<MyNS::istring, EntityState> Entity;

前処理された出力を見ると、class Entityこの typedef の前に 2 つの前方宣言があることがわかります。ただし、の実際の定義はclass Entity前処理された出力にはありませんが、新しいエンティティ マップと同じ名前空間にあります (そうではありませんMyNSが...)。このエラーの原因は前方宣言ですか? そして、これがMSVCで有効であり、Clangの衒学のために機能しない方法はありますか?

編集:手元にMSVCはありませんが、ここに私が得ているエラーの種類を示すためにまとめたスニペットがあります(すべてが小さなスペースに収まるように定義を簡略化しました)。これにより、Clang でコンパイルしようとしたときに発生するのと同じエラーが発生します。これは MSVC で機能しますか?

namespace TheNS {

    class Entity;

    struct EntityState
    {
        std::string aString, anotherString;
        int anInt;

        EntityState() {}

        EntityState(std::string a, std::string b, int i)
        {
            // constructor
        }
    };

    typedef std::map<std::string, EntityState> Entity;

    class Entity
    {
    public:
        void SomeFunction();

    private:
        int m_aVar;

    };

}    
4

1 に答える 1

2

はい、正しくありません。MSVC でコンパイルする場合は、コンパイルしないでください。おそらく、コンパイラのバグです。前方宣言はコンパイラに、それTheNS::Entityはクラスであり、それ以外のものは何もないことを伝えます (enum、union、または typedef ではありません)。本当に、あなたのコードは

class Entity;   
typedef int Entity;

もちろん、それは間違っています。

n3337 9.1/2

クラスキー識別子のみで構成される宣言。現在のスコープでの名前の再宣言、またはクラス名としての識別子の前方宣言です。クラス名を現在のスコープに導入します。

だから、この後

class Entity;

Entityコンパイルは、それがクラス名として使用されることを知っています。この名前は、(同じスコープ内で) 関数として再宣言できます。この場合、クラスclass Entityを使用する場合は、 を使用する必要がありますEntity(またはEntity、コメントにあるように typedef で名前を再宣言します)。

7.1.3/6

特定のスコープでは、 typedef 指定子を使用して、そのスコープで宣言された型の名前を再定義して、別の型を参照してはなりません。[ 例:

class complex { /∗ ... ∗/ };
typedef int complex; // error: redifinition

— 終了例 ]

于 2012-10-02T10:10:16.390 に答える