10

C++11 を使用してマップのマップを初期化しようとしています。私のコンパイラは VS 2013 Express です。

unordered_map<EnumType, unordered_map<string, string>> substitutions = {
    {
        Record::BasementType,
        {
            { "0", "" },
            { "1", "Slab or pier" },
            { "2", "Crawl" }
        }
    },
    {
        Record::BuildingStyle,
        {
            { "0", "" },
            { "1", "Ranch" },
            { "2", "Raised ranch" }
        }
    },
    // ... and so on
};

コンパイルはできましたが、ntdll.dll 内でブレークポイントが発生しています。ただし、このコードの簡略版:

unordered_map<EnumType, unordered_map<string, string>> substitutions = {
    {
        Record::BasementType,
        {
            { "0", "" },
            { "1", "Slab or pier" },
            { "2", "Crawl" }
        }
    },
    // *nothing more*
};

正常に動作します。

マップに複数のペアがある場合、これが機能しないのはなぜですか? それをより良くする方法は?

4

2 に答える 2

19

これは既知のコンパイラ バグです ( http://connect.microsoft.com/VisualStudio/feedback/details/800104/ ) 。コンパイラは、初期化子リストの一時変数によって混乱し、個々のオブジェクトを繰り返し破棄することさえできます。これはサイレントで悪いコード生成であるため、コンパイラ チームに優先的に修正するよう依頼しました。

于 2013-10-28T22:50:34.120 に答える
0

私が何年にもわたって発見したこの回避策は、make_pairペアごとのブラケット初期化子の代わりに初期化子リストで使用することです({ ... }):

std::unordered_map<Record, std::unordered_map<std::string, std::string>> testmap = {
    make_pair(Record::BasementType, std::unordered_map<std::string, std::string>({ { "0", "" }, { "1", "Slab or pier" }, { "2", "Crawl" } })),
    make_pair(Record::BuildingStyle, std::unordered_map<std::string, std::string>({ { "0", "" }, { "1", "Slab or pier" }, { "2", "Crawl" } })),
    // ... and so on
};

コンパイラは、一時的な初期化子の問題に関係なく、そこからペアをうまく​​処理できるようです。

あなたの場合、内部の unordered_map イニシャライザを明示的にキャストする必要があることに注意してください。これは、複数の stl コンテナ タイプがそのように初期化される可能性があるためです。make_pairまたは、同じキャスト結果を持つテンプレート タイプを指定することもできます。make_pair<Record, std::unordered_map<std::string, std::string>>(...)

この回避策は、私のようにまだ VS2013 を使用している人に役立つかもしれません。

于 2018-06-05T20:44:00.443 に答える