私は C++ と STL の専門家ではありません。
Map 内の構造をデータとして使用します。キーはクラスC1です。同じデータにアクセスしたいのですが、別のキー C2 も使用します (C1 と C2 は無関係な 2 つのクラスです)。
これは、データを複製せずに可能ですか? グーグルで検索してみましたが、理解できる答えを見つけるのに苦労しました。
これは、boost ライブラリがサポートされていない組み込みターゲット用です。
誰か助けてくれませんか?
へのポインターを値Data
として格納するstd::map
ことができ、同じデータを指す異なるキーを持つ 2 つのマップを持つことができます。
このようなデータの共有所有権の場合、次のようなスマートポインターstd::shared_ptr
が適切なオプションだと思います。
#include <map> // for std::map
#include <memory> // for std::shared_ptr
....
std::map<C1, std::shared_ptr<Data>> map1;
std::map<C2, std::shared_ptr<Data>> map2;
のインスタンスは、Data
を使用して割り当てることができますstd::make_shared()
。
標準ライブラリにはありませんが、Boost は提供していますboost::multi_index
私は少し読み違えていたことを認めなければなりません。値ではなく、異なるタイプの 2 つのキーが必要であることに実際には気付きませんでした。ただし、その解決策は以下の内容に基づいています。他の答えには、そのために必要なものがほとんどあります。ユニバーサルルックアップ関数を作成できることを付け加えておきます:(C++ 14っぽい疑似コード)。
template<class Key>
auto lookup (Key const& key) { }
そして、それをあなたの鍵に特化させます (おそらく SFINAE よりも簡単です)
template<>
auto lookup<KeyA> (KeyA const& key) { return map_of_keys_a[key]; }
についても同様ですKeyB
。
それをクラスにカプセル化したい場合は、 に変更lookup
するのが当然の選択operator[]
です。
私が 60 秒で思いつく最も簡単な解決策: (最も単純な意味は、それが本当に熟考されるべきであることを意味します)。また、デフォルトとして切り替えunordered_map
ます。
map<Key, Data> data;
map<Key2, Key> keys;
経由でアクセスしdata[keys["multikey"]]
ます。
これは明らかにいくらかのスペースを無駄にします (Key
タイプのオブジェクトを複製します) が、それらはタイプよりもはるかに小さいと想定していますData
。
別の解決策は、ポインターを使用することです。重複の唯一のコストは(スマート)ポインターです。
map<Key, shared_ptr<Data>> data;
のオブジェクトはData
、それを指すキーが少なくとも 1 つある限り存続します。
これらの場合に私が通常行うことは、所有されていないポインターを使用することです。データをベクターに保存します。
std::vector<Data> myData;
次に、ポインターを各要素にマップします。ただし、ベクトルの将来の成長のためにポインターが無効になる可能性があるため、この場合はベクトル インデックスを使用することを選択します。
std::map<Key1, int> myMap1;
std::map<Key2, int> myMap2;
データ コンテナーをクライアントに公開しないでください。要素の挿入と削除を特定の関数にカプセル化して、どこにでも挿入し、どこにでも削除します。
すべてのデータをプレーンにstd::list
保持し、std::map
任意のキー値をリストを指すイテレータにマッピングするさまざまなオブジェクトを検討できます。
std::list<Data> values;
std::map<C1, std::list<Data>::iterator> byC1;
std::map<C2, std::list<Data>::iterator> byC2;
つまり、多かれ少なかれ生のポインターをいじる代わりに、プレーンなイテレーターを使用します。また、 a へのイテレータには、std::list
非常に優れた無効化保証があります。
私は同じ問題を抱えていました。最初は、共有ポインター用に2つのマップを保持するのは非常にクールに聞こえました。ただし、この 2 つのマップを管理する必要があります (挿入、削除など)。
これを行う他の方法を思いついたよりも。私の理由は次のとおりです。xy または radius-angle でデータにアクセスします。各ポイントはデータを保持すると考えてください。ただし、ポイントはデカルト x,y または radius-angle として記述できます。
だから私は次のような構造体を書きました
struct MyPoint
{
std::pair<int, int> cartesianPoint;
std::pair<int, int> radianPoint;
bool operator== (const MyPoint& rhs)
{
if (cartesianPoint == rhs.cartesianPoint || radianPoint == rhs.radianPoint)
return true;
return false;
}
}
その後、それをキーとして使用できましたが、
std::unordered_map<MyPoint, DataType> myMultIndexMap;
あなたのケースが同じか、このシーンに合わせて調整できるかどうかはわかりませんが、オプションになる可能性があります.