descargar baker applepi apple c++ stl map compile-time

c++ - baker - Usando std:: map<K, V> donde V no tiene un constructor usable por defecto



apple pi baker windows (9)

Cuando utiliza una anulación de operador en C ++, es mejor mantenerse lo más cerca posible con la semántica del operador en el caso predeterminado. La semántica del valor predeterminado. operator [] es la sustitución de un miembro existente en una matriz. Parece que std :: map dobla las reglas un poco. Eso es desafortunado, porque lleva a este tipo de confusión.

Tenga en cuenta que la documentación ( http://www.sgi.com/tech/stl/Map.html ) para el operador [] en std :: map dice: "Devuelve una referencia al objeto que está asociado con una clave en particular. el mapa ya no contiene dicho objeto, el operador [] inserta el objeto predeterminado tipo_datos (). "

Sugeriría que trate el reemplazo y la inserción de manera diferente. Desafortunadamente, esto significa que necesita saber cuál es requerido. Eso puede significar primero hacer una búsqueda en el mapa. Si el rendimiento es un problema, es posible que deba encontrar una optimización donde pueda probar la membresía e insertar con una búsqueda.

Tengo una tabla de símbolos implementada como std::map . Para el valor, no hay forma de construir legítimamente una instancia del tipo de valor a través de un constructor predeterminado. Sin embargo, si no proporciono un constructor predeterminado, obtengo un error de compilación y si hago que el constructor sea afirmativo, mi programa compila bien, pero se cuelga dentro del map<K,V>::operator [] si intento usarlo para agregar un nuevo miembro

¿Hay alguna manera de que pueda conseguir que C ++ no permita el map[k] como un valor l en el momento de la compilación (mientras lo permite como un valor r)?

Por cierto: sé que puedo insertar en el mapa usando Map.insert(map<K,V>::value_type(k,v)) .

Editar: varias personas han propuesto una solución que equivale a alterar el tipo de valor para que el mapa pueda construir uno sin llamar al constructor predeterminado. Esto tiene exactamente el resultado opuesto de lo que quiero porque oculta el error hasta más tarde. Si estuviera dispuesto a tener eso, simplemente podría eliminar la afirmación del constructor. Lo que quiero es hacer que el error suceda incluso antes; en tiempo de compilación Sin embargo, parece que no hay forma de distinguir entre los usos r-value y l-value del operator[] así que parece que lo que quiero no se puede hacer, así que tendré que prescindir de usarlo todo junto.


Derive una nueva clase de std::map<K,V> y cree su propio operator[] . Haz que devuelva una referencia constante, que no se puede usar como un valor l.


Es un poco feo, pero una forma de evitar esto es agregar una variable miembro que rastrea si una instancia es válida o no. Su constructor predeterminado marcará una instancia como no válida, pero todos sus otros constructores marcan la instancia como válida.

Asegúrese de que su operador de asignación transfiere correctamente la nueva variable miembro.

Modifique su destructor para ignorar instancias inválidas.

Modifique todas sus otras funciones miembro para arrojar / error / afirmar cuando operan en una instancia no válida.

Luego puede usar su objeto en un mapa y siempre que solo use objetos que fueron construidos correctamente, su código funcionará bien.

De nuevo, esto es una solución alternativa si desea usar el mapa STL y no desea utilizar insert y find en lugar de operator [].


No estoy seguro de por qué se compila para usted, creo que el compilador debería haber capturado su constructor faltante.

¿qué hay de usar

map<K,V*>

en lugar de

map<K,V> ?


No se puede hacer que el compilador diferencie entre los dos usos del operador [], porque son la misma cosa. El operador [] devuelve una referencia, por lo que la versión de asignación solo está asignando a esa referencia.

Personalmente, nunca uso el operador [] para mapas para otra cosa que no sea el código demo rápido y sucio. Use insert () y find () en su lugar. Tenga en cuenta que la función make_pair () hace que la inserción sea más fácil de usar:

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

En C ++ 11, también puedes hacer

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

incluso si el constructor de copiar / mover no está incluido.


Si el valor-tipo no es predecible-construible, entonces el operator[] simplemente no funcionará para usted.

Lo que puede hacer, sin embargo, es proporcionar funciones gratuitas que obtengan y establezcan valores en un mapa para su comodidad.

P.ej:

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; } }

También podría considerar un getter como dict.get(key [, default]) en Python (que devuelve el valor predeterminado proporcionado si la clave no está presente (pero tiene un problema de usabilidad en el hecho de que siempre debe construirse el valor predeterminado, incluso si saber que la clave está en el mapa).


Su V no tiene un constructor predeterminado, por lo que no puede esperar que std::map<K,V> std::map<K,V>::operator[] sea ​​utilizable.

Un std::map<K, boost::optional<V> > tiene un mapped_type que es mapped_type y es probable que tenga la semántica que desee. Consulte la documentación de Boost.Optional para obtener detalles ( deberá tenerlos en cuenta).


Usa el map<K,V>::at() . map<K,V>::operator [] intentará construir por defecto un elemento si la clave proporcionada no existe aún.


puedes especializar std :: map para tu tipo de valor. No digo que sea una buena idea, pero se puede hacer. Especializo scoped_ptr<FILE> ''s dtor para fclose lugar de delete .

Algo como:

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

Esto debería permitirle insertar el código que desea en el operador [] para su tipo. Desafortunadamente, no sé de ninguna manera en el c ++ actual para devolver solo los valores r. En c ++ 0x, es posible que pueda usar:

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

Esto devolverá una referencia de valor R (&&).