質問

デフォルト値を指定する方法はありますか std::mapさんの operator[] キーが存在しない場合に返す?

役に立ちましたか?

解決

いいえ、ありません。最も簡単な解決策は、これを行うには、あなた自身の自由なテンプレート関数を記述することです。ような何かます:

#include <string>
#include <map>
using namespace std;

template <typename K, typename V>
V GetWithDef(const  std::map <K,V> & m, const K & key, const V & defval ) {
   typename std::map<K,V>::const_iterator it = m.find( key );
   if ( it == m.end() ) {
      return defval;
   }
   else {
      return it->second;
   }
}

int main() {
   map <string,int> x;
   ...
   int i = GetWithDef( x, string("foo"), 42 );
}
<時間>

C ++ 11を更新する

目的:一般的な連想コンテナ用のアカウントだけでなく、オプションのコンパレータとアロケータのパラメータ

template <template<class,class,class...> class C, typename K, typename V, typename... Args>
V GetWithDef(const C<K,V,Args...>& m, K const& key, const V & defval)
{
    typename C<K,V,Args...>::const_iterator it = m.find( key );
    if (it == m.end())
        return defval;
    return it->second;
}

他のヒント

これは正確に質問に答えていませんが、

は、私がこのようなコードで、問題を回避しています:

struct IntDefaultedToMinusOne
{
    int i = -1;
};

std::map<std::string, IntDefaultedToMinusOne > mymap;

C++の標準(23.3.1.2)を指定することは、新しく挿入された値がデフォルトの構築で map そのものはどんな方はそれができていました。お客様の選択:

  • の値型のデフォルトのコンストラクタinitialisesでの価値の希望
  • ラップで地図に自分のクラスを提供するデフォルト値は、実装 operator[] を挿入するデフォルトです。
template<typename T, T X>
struct Default {
    Default () : val(T(X)) {}
    Default (T const & val) : val(val) {}
    operator T & () { return val; }
    operator T const & () const { return val; }
    T val;
};

<...>

std::map<KeyType, Default<ValueType, DefaultValue> > mapping;

より一般的なバージョン、C++98/03 およびその他のコンテナをサポート

汎用の連想コンテナーで動作します。唯一のテンプレート パラメーターはコンテナー タイプ自体です。

サポートされているコンテナ: std::map, std::multimap, std::unordered_map, std::unordered_multimap, wxHashMap, QMap, QMultiMap, QHash, QMultiHash, 、など。

template<typename MAP>
const typename MAP::mapped_type& get_with_default(const MAP& m, 
                                             const typename MAP::key_type& key, 
                                             const typename MAP::mapped_type& defval)
{
    typename MAP::const_iterator it = m.find(key);
    if (it == m.end())
        return defval;

    return it->second;
}

使用法:

std::map<int, std::string> t;
t[1] = "one";
string s = get_with_default(t, 2, "unknown");

以下は、ラッパー クラスを使用した同様の実装です。これは、メソッドに似ています。 get()dict Python で次のように入力します。 https://github.com/hltj/wxMEdit/blob/master/src/xm/xm_utils.hpp

template<typename MAP>
struct map_wrapper
{
    typedef typename MAP::key_type K;
    typedef typename MAP::mapped_type V;
    typedef typename MAP::const_iterator CIT;

    map_wrapper(const MAP& m) :m_map(m) {}

    const V& get(const K& key, const V& default_val) const
    {
        CIT it = m_map.find(key);
        if (it == m_map.end())
            return default_val;

        return it->second;
    }
private:
    const MAP& m_map;
};

template<typename MAP>
map_wrapper<MAP> wrap_map(const MAP& m)
{
    return map_wrapper<MAP>(m);
}

使用法:

std::map<int, std::string> t;
t[1] = "one";
string s = wrap_map(t).get(2, "unknown");

はデフォルト値を指定する方法はありません - それは、常にデフォルト(ゼロパラメータコンストラクタ)によって構築された値です。

ファクトoperator[]はおそらく値マップ内の特定のキーのために存在しない場合、それはデフォルトコンストラクタからの値を使用して新しいものを挿入しますと、あなたが期待する以上にしてます。

C ++ 17には、まさにこれを行いtry_emplaceを提供します。これは、ペア値コンストラクタのためのキーと引数リストを受け取り、返します。iteratorbool:<のhrefを=「http://en.cppreference.com/w/cpp/container/map/try_emplace」のrel = "nofollowをnoreferrer"> http://en.cppreference.com/w/cpp/container/map/try_emplace の

他の回答が言うように

は値が、デフォルトのコンストラクタを使用して初期化されます。しかし、単純型の場合にはそれを追加することが有用であり、値はゼロに初期化される(または事実である(値は、初期化によってゼロ(例えば、整数、浮動小数点、ポインタまたはPOD(計画古いデータ)型として整数型)同じこと)、C ++のバージョンに応じて使用されている)。

とにかく、bottomlineは、単純型とマップがすることを自動的に新しいアイテムをゼロに初期化されます。だから、いくつかのケースでは、明示的にデフォルトの初期値を指定心配する必要はありません。

std::map<int, char*> map;
typedef char *P;
char *p = map[123],
    *p1 = P(); // map uses the same construct inside, causes zero-initialization
assert(!p && !p1); // both will be 0

を参照してください。タイプ名の後の括弧は、問題の詳細については、新しいですかとの違いを確認してください。

たぶん、あなたが欲しい、デフォルト値で割り当てるカスタムアロケータを与えることができます。

template < class Key, class T, class Compare = less<Key>,
       class Allocator = allocator<pair<const Key,T> > > class map;

回避策の一つではなくmap::at()[]を使用することです。 キーが存在しない場合は、atは例外をスローします。 でもよりよい、これはまた、ベクトルのために働くので、あなたはベクターでマップを入れ替えることがジェネリックプログラミングに適しています。

そのカスタム値(等-1)コードでさらに下に処理することができるので、

未登録キーのカスタム値を使用するのは危険であり得ます。例外を除いて、それはバグを発見する方が簡単です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top