web-dev-qa-db-ja.com

タイプトレイトの静的std :: unordered_mapを初期化する方法は?

次のタイプの特性がある場合、Fieldsをいくつかのstd::pairsで初期化するにはどうすればよいですか?

template <>
struct ManagerDataTrait<Person>
{
    static const std::unordered_map<std::string, std::string> Fields;
    // ...
};

ラムダを使用してみましたが、Visual Studioによると、Fieldsは明示的に特殊化できるエンティティではありません。

template <>
const std::unordered_map<std::string, std::string> ManagerDataTrait<Person>::Fields = []{
    std::unordered_map<std::string, std::string> fields;
    fields.insert(std::make_pair("height", "FLOAT"));
    fields.insert(std::make_pair("mass", "FLOAT"));
    return fields;
};

このような静的メンバーをトレイトで使用する方法がない場合、どの代替手段で情報をトレイトに保存する必要がありますか? (FieldsはSQLデータベース構造を保持します。)

更新:メンバーもconstである可能性がありますが、それは重要ではありません。

11
danijar

Kerrek SBの答えは、一般的に正しい答えです。

const std::unordered_map<std::string, std::string> ManagerDataTrait<Person>::Fields{
  { "blah", "blah" }
  // ...
};

(N.B. no template<>スペシャライゼーションではなく、スペシャライゼーションのメンバーを定義しているため)

ただし、これはVisual C++ではサポートされていないため、もう1つの方法は、関数呼び出しを使用してマップを初期化し、関数から目的のコンテンツを含むマップを返すことです。

std::unordered_map<std::string, std::string>
getFields()
{
  std::unordered_map<std::string, std::string> fields;
  fields["blah"] = "blah";
  // ...
  return fields;
}

const std::unordered_map<std::string, std::string> ManagerDataTrait<Person>::Fields = getFields();

ラムダは同じことを行うための単なる構文糖衣です。構文が少し醜いので、ラムダを使用する方が明確かどうかはわかりません。

10
Jonathan Wakely

ブレースリストからマップを初期化できることに気づきましたか?

std::unordered_map<std::string, std::string> m { { "a", "bc" }
                                               , { "b", "xy" }
//                                               ...
                                               };
21
Kerrek SB

Visual C++は、ブレースリストからの静的初期化をサポートするようになったため、次のようなことができます。

const std::unordered_map<std::string, std::string> ManagerDataTrait<Person>::Fields{ { "abc", "xyz" }, { "cde", "zyx" } ...};
2
NiRuKa