2010-08-02 25 views
5

Atar para compilar el programa siguiente con Visual Studio 10, consigo gran cantidad de errores de compilación:Problema con std :: make_tuple en C++ 0x

#include "stdafx.h" 

#include <tuple> 
#include <string> 
#include <map> 
#include <iostream> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    typedef std::tuple<std::string, std::string> key_t; 
    typedef std::map<key_t, std::string> map_t; 

    map_t the_map; 

    auto k = std::make_tuple("one", "two"); 
    the_map[k] = "the value"; 

    auto q = std::make_tuple("one", "two"); 

    auto i = the_map.find(q); 
    std::cout << i->second << std::endl; 

    return 0; 
} 

de error 1 error C2664: 'std :: basic_string < _Elem, _Traits, _Ax> :: basic_string (const std :: basic_string < _Elem, _Traits, _Ax> &) ': no ​​se puede convertir el parámetro 1 de' const key_t 'a' const std :: basic_string < _Elem, _Traits, _Ax > & 'c: \ archivos de programa (x86) \ microsoft visual studio 10.0 \ vc \ include \ tuple 127 1 tupla

procedentes de la línea:

std::cout << i->second << std::endl; 

Lo extraño es, como mínimo, desde mi punto de vista, si cambio de estas líneas:

auto k = std::make_tuple("one", "two"); 
the_map[k] = "the value"; 

a

the_map[std::make_tuple("one", "two")] = "p"; 

la programa compila Entonces mi pregunta es, por supuesto, ¿por qué? Creo que tiene algo que ver con make_tuple y mover la semántica - pero no entiendo lo que ..

Respuesta

4

Al parecer, el error proviene de hecho de la línea the_map[k] = "the value";

Cuando se utiliza el operador [] en un mapa, la biblioteca intenta crear un objeto std::pair<Key,Value>. En su caso, esto se convierte en std::pair<std::tuple<std::string,std::string>,std::string>.

Sin embargo, si se utiliza una variable intermedia k, el constructor de std :: par que se llama es: (copia pegada-lib de la norma)

_Pair_base(const _Ty1x& _Val1, _Ty2x&& _Val2) 
     : first(_Val1), second(_STD move(_Val2)) 
     { // construct from specified values 
     } 

Este constructor está tratando de hacer una copia de tu key_t. Desafortunadamente, la implementación tupla de MSVC++ está bloqueada en este momento y la copia no se puede compilar (ver también esto: C++0x : are tuples of tuples allowed?)

Puedo diagnosticar más, porque esta implementación no solo está estropeada sino que también es muy complicada.

Las tuplas de Boost deberían funcionar pero no tienen un operador <, por lo que no puede usarlas.

El "mejor" solución por el momento es escribir the_map.insert(std::make_pair(k, "the value"));

+0

Gracias - funciona y mi código original se verá bien con su solución. – baardk

+0

Tenga en cuenta que también puede escribir 'the_map [std :: move (k)] =" el valor "' pero esto "destruirá" su variable 'k' (consulte algunos artículos sobre la semántica de movimientos si no ve qué Quiero decir por destruir). – Tomaka17

+0

Agradable. Publiqué el problema en algún sitio de MS Connect, para que puedan verificar si es un error o qué. – baardk

2

Esto parece un error en VS10, por alguna razón que está tratando de convertir el tipo clave para el tipo de valor.

Esta versión simplificada también falla.

typedef std::map<std::tuple<int, int>, int> map_t; 

map_t the_map; 

map_t::key_type k = std::make_tuple(1,2); 
the_map[k] = 3; 

produce los siguientes: C2440

error: 'inicialización': no ​​se puede convertir de 'const std :: TR1 :: tupla < _Arg0, _Arg1>' a 'int'

+0

Ah, buena simplificación. – baardk

Cuestiones relacionadas