52

として実装されたシンボルテーブルがありますstd::map。値の場合、既定のコンストラクターを介して値型のインスタンスを正当に構築する方法はありません。ただし、デフォルトのコンストラクターを提供しないとコンパイラ エラーが発生し、コンストラクターをアサートすると、プログラムは正常にコンパイルされますが、map<K,V>::operator []それを使用して新しいメンバーを追加しようとすると内部でクラッシュします。

C++ をmap[k]コンパイル時に (r 値として許可しながら) l 値として許可しないようにする方法はありますか?


ところで: を使用してマップに挿入できることはわかっていますMap.insert(map<K,V>::value_type(k,v))


編集:値の型を変更して、デフォルトのコンストラクターを呼び出さずにマップを構築できるようにする解決策を何人かの人々が提案しています。これは、後でエラーを非表示にするため、私が望むものとは正反対の結果になります。そうしたければ、単純にコンストラクターからアサートを削除できます。私が望むのは、エラーをさらに早く発生させることです。コンパイル時に。ただし、r値とl値の使用を区別する方法がないようですoperator[]ので、私が望むことはできないようですので、一緒に使用することはやめてください。

4

10 に答える 10

51

operator[] の 2 つの使用法は同じものであるため、コンパイラーにそれらを区別させることはできません。Operator[] は参照を返すため、割り当てバージョンはその参照に割り当てられているだけです。

個人的には、素早いデモ コード以外のマップに operator[] を使用することはありません。代わりに insert() と find() を使用してください。make_pair() 関数を使用すると、挿入が簡単になることに注意してください。

m.insert( make_pair( k, v ) );

C++11では、次のこともできます

m.emplace( k, v );
m.emplace( piecewise_construct, make_tuple(k), make_tuple(the_constructor_arg_of_v) );

コピー/移動コンストラクターが提供されていない場合でも。

于 2009-12-20T12:17:20.027 に答える
5

デフォルトのコンストラクターがないため、実際に使用できるとは期待できませVん 。std::map<K,V> std::map<K,V>::operator[]

Aにstd::map<K, boost::optional<V> > デフォルトで構築可能なamapped_typeがあり、必要なセマンティクスを持っている可能性があります。詳細については、Boost.Optionalのドキュメントを参照してください (注意必要です)。

于 2009-12-20T13:03:42.053 に答える
4

値の型がデフォルトで構築可能でない場合は、うまくoperator[]いきません。

ただし、便宜上、マップ内の値を取得および設定する無料の関数を提供することはできます。

例えば:

template <class K, class V>
V& get(std::map<K, V>& m, const K& k)
{
    typename std::map<K, V>::iterator it = m.find(k);
    if (it != m.end()) {
        return it->second;
    }
    throw std::range_error("Missing key");
}

template <class K, class V>
const V& get(const std::map<K, V>& m, const K& k)
{
    typename std::map<K, V>::const_iterator it = m.find(k);
    if (it != m.end()) {
        return it->second;
    }
    throw std::range_error("Missing key");
}

template <class K, class V>
void set(std::map<K, V>& m, const K& k, const V& v)
{
    std::pair<typename std::map<K, V>::iterator,bool> result = m.insert(std::make_pair(k, v));
    if (!result.second) {
        result.first->second = v;
    }
}

また、Pythonのような getter を検討することもできdict.get(key [, default])ます (キーが存在しない場合は、提供されたデフォルトを返します (ただし、キーがマップにあることがわかっている場合でも、常にデフォルトを構築する必要があるため、使いやすさの問題があります)。

于 2009-12-20T15:25:56.603 に答える
1

なぜコンパイルされるのかわかりませんが、コンパイラは不足しているコンストラクタをキャッチする必要があると思います。

使用はどうですか

map<K,V*>

それ以外の

map<K,V> ?
于 2009-12-20T15:58:59.003 に答える
0

値の型に合わせて std::map を特殊化できます。それが良い考えだとは言いませんが、それは可能です。scoped_ptr<FILE>の dtor を のfclose代わりに特化しましたdelete

何かのようなもの:

 template<class K, class Compare, class Allocator>
 my_value_type& std::map<K,my_value_type,Compare,Allocator>::operator[](const K& k) 
 {
   //...
 }

これにより、タイプの operator[] に必要なコードを挿入できるようになります。残念ながら、現在の c++ で r 値のみを返す方法を知りません。c++0x では、以下を使用できる場合があります。

 template<class K, class Compare, class Allocator>
 my_value_type&& std::map<K,my_value_type,Compare,Allocator>::operator[](const K& k) 
 {
   //...
 }

これにより、R 値参照 (&&) が返されます。

于 2009-12-20T15:47:48.900 に答える