std::map valor predeterminado
¿Hay alguna forma de especificar el valor predeterminado std::map
's operator[]
devuelve cuando no existe una clave?
9 answers
No, no lo hay. La solución más simple es escribir su propia función de plantilla gratuita para hacer esto. Algo como:
#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 );
}
Actualización de C++11
Propósito: Tenga en cuenta los contenedores asociativos genéricos, así como los parámetros comparadores y asignadores opcionales.
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 15:49:00
Aunque esto no responde exactamente a la pregunta, he eludido el problema con un código como este:
struct IntDefaultedToMinusOne
{
int i = -1;
};
std::map<std::string, IntDefaultedToMinusOne > mymap;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-11 08:32:59
El estándar de C++ (23.3.1.2) especifica que el valor recién insertado se construye por defecto, por lo que map
no proporciona una forma de hacerlo. Sus opciones son:
- Dé al tipo de valor un constructor predeterminado que lo inicialice al valor que desee, o
- Envuelva el mapa en su propia clase que proporciona un valor predeterminado e implementa
operator[]
para insertar ese valor predeterminado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-25 12:07:42
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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-08 17:49:00
Versión Más General, Soporte C++98/03 y Más Contenedores
Funciona con contenedores asociativos genéricos, el único parámetro de plantilla es el propio tipo de contenedor.
Admite contenedores: std::map
, std::multimap
, std::unordered_map
, std::unordered_multimap
, wxHashMap
, QMap
, QMultiMap
, QHash
, QMultiHash
, etc.
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;
}
Uso:
std::map<int, std::string> t;
t[1] = "one";
string s = get_with_default(t, 2, "unknown");
Aquí hay una implementación similar mediante el uso de una clase wrapper, que es más similar al método get()
de tipo dict
en 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);
}
Uso:
std::map<int, std::string> t;
t[1] = "one";
string s = wrap_map(t).get(2, "unknown");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-19 17:21:47
No hay forma de especificar el valor por defecto - siempre es valor construido por el valor por defecto (constructor de parámetro cero).
De hecho, operator[]
probablemente hace más de lo que espera, ya que si no existe un valor para la clave dada en el mapa, insertará una nueva con el valor del constructor predeterminado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-25 17:46:59
C++17 proporciona try_emplace
que hace exactamente esto. Toma una clave y una lista de argumentos para el constructor de valores y devuelve un par: an iterator
y a bool
.: http://en.cppreference.com/w/cpp/container/map/try_emplace
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-10 17:22:32
El valor se inicializa usando el constructor predeterminado, como dicen las otras respuestas. Sin embargo, es útil agregar que en el caso de tipos simples (tipos integrales como int, float, pointer o POD (plan old data)), los valores se inicializan a cero (o se ponen a cero por inicialización de valor (que es efectivamente lo mismo), dependiendo de la versión de C++ que se use).
De todos modos, la línea de fondo es que los mapas con tipos simples inicializarán cero los nuevos elementos automáticamente. Así que en algunos casos, no hay necesidad de preocuparse por especificar explícitamente el valor inicial predeterminado.
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
Ver ¿Los paréntesis después del nombre del tipo hacen una diferencia con nuevo? para más detalles sobre el asunto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:30
Tal vez usted puede dar un asignador personalizado que asignar con un valor predeterminado que desee.
template < class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key,T> > > class map;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-25 12:06:45