2016-06-13 10 views
1

ユースケース:レコードのバッファ。ここに基本的な考え方があります。 レコード構造体のコンストラクタは、要素がマップに追加されたときにレコード番号として使用されるキーを認識する必要があります。 もちろん、これはより多くのコードで行うことができますが、これは私にとって最も優雅に見えます。 は最小限符号化:マップ内の構造体のコンストラクタのアクセスキー

#include <whatever> 
struct record 
{ 
    string foo; 
    record(unsigned irec) { foo=readrecord(irec); } 
}; 

map<unsigned,record>recbuf; 

int main() 
{ 
    // if the element is not yet in the map, it should be read. 
    string foo_ten=recbuf[10].foo; 
    // do something with the result 
    printf("foo_ten: %s\n",foo_ten.c_str()); 
    return 0; 
} 

EDIT1:上記のコードは動作しません。 これを動作させる方法はありますか? EDIT2: 私は別のマップを追加mapplusクラスを派生::演算子[]:

template<class _Kty, class _Ty, class _Pr = less<_Kty>, class _Alloc = allocator<pair<const _Kty, _Ty> > >class mapplus :public map<_Kty, _Ty, _Pr, _Alloc> 
{ 
public: 
    mapped_type& operator[](const _Kty &_Keyval) 
    { // find element matching _Keyval or insert with default mapped 
     iterator _Where = _Mybase::lower_bound(_Keyval); 
     if (_Where == _Mybase::end() 
      || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode()))) 

      _Where = _Mybase::emplace_hint(_Where, 
       _Keyval, 
       _Ty(_Keyval)); 
     return (_Where->second); 
    } 
}; 

これは、作業を行います。私はまだ私が不必要に複雑な方法でこれをしたことを指摘するコメントに興味があります。私はしましたか?あまり苦労せずにやることはできますか?

+1

だから、正確にあなたの質問は何ですか?デフォルトのコンストラクタなしでも動作しますか? –

答えて

0

したがって、デフォルトのコンストラクタではなくrecord(unsigned)コンストラクタを使用してrecordオブジェクトを作成する必要があります。

残念ながら、operator[]reference)でこれを行う方法はありません:

kはコンテナ内の要素のキーと一致する場合、そのマッピングされた値への参照を返す 機能。

kがコンテナ内の任意の要素のキーと一致しない場合、 関数は、そのキーを持つ新しい要素を挿入し、その参照された値に参照 を返します。要素にマップされた値が割り当てられていない場合でも、コンテナ のサイズは1つずつ増加します( 要素はデフォルトコンストラクタを使用して構成されています)。

私は私のためにそれは悪いデザインのように思える、std::mapためoperator[]に過負荷をかけることをお勧めしません。

ただし、insertまたはemplace(C++ 11)などの他の方法で行うこともできます。 参照は、例えば、この回答:Using std::map<K,V> where V has no usable default constructor

テスト済み例:

#include <map> 
#include <sstream> 
#include <iostream> 


std::string readRecord(int id) 
{ 
    std::stringstream stream; 
    stream << id; 
    return stream.str(); 
} 

struct Record 
{ 
    Record(int id) 
     : foo(readRecord(id)) 
    { 
    } 

    std::string foo; 
}; 

int main() 
{ 
    std::map<int, Record> m; 
    for (int i = 0; i < 10; ++i) 
     m.insert(std::make_pair(i, Record(i))); 

    std::cout << m.at(5).foo << std::endl; 
    // std::cout << m[7].foo << std::endl; // error 'Record::Record': no appropriate default constructor available 

    return 0; 
} 
+0

以前のディスカッションを指摘してくれてありがとう。それは有用であり、私がやったことをやっていることを示唆しています。そして、それが役に立つようブーストするための参考になりました。私は、より具体的にすることで "悪いデザイン"の問題を解決できるかどうかを見ます。整数キーのみ。これは四角形のブラケット参照も可能な解決策を望むには十分に基本的です。 – Jan

+0

@Jan、あなたのプログラム/ライブラリの非標準STLコンテナセマンティクスに驚くかもしれないが、他のプログラマはhttps://en.wikipedia.org/wiki/Principle_of_least_astonishmentに違反していることにご注意ください。私は判断や何かではない、私の個人的な意見を述べる:) –

関連する問題