[c++] std :: map 기본값

키가 존재하지 않을 때 기본값 std::mapoperator[]반환 을 지정하는 방법 이 있습니까?



답변

아니, 없습니다. 가장 간단한 해결책은이 작업을 수행하기위한 무료 템플릿 함수를 작성하는 것입니다. 다음과 같은 것 :

#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자체적으로이를 수행하는 방법을 제공하지 않습니다. 선택 사항은 다음과 같습니다.

  • 값 유형에 원하는 값으로 초기화하는 기본 생성자를 제공하거나
  • 기본값을 제공하고 operator[]해당 기본값을 삽입하도록 구현하는 자체 클래스로 맵을 래핑합니다 .


답변

보다 일반적인 버전, 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");

다음은 Python get()dict유형 메소드와 더 유사한 래퍼 클래스를 사용하여 유사한 구현입니다 . 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");


답변

C ++ 17은 try_emplace정확히이 기능 을 제공합니다 . 값 생성자에 대한 키와 인수 목록을 가져 와서 an iterator과 a 쌍을 반환 합니다 bool. : http://en.cppreference.com/w/cpp/container/map/try_emplace


답변

기본값을 지정하는 방법은 없습니다. 항상 기본값 (제로 매개 변수 생성자)에 의해 구성된 값입니다.

실제로 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;