2010-08-02 12 views
5

Tying per compilare il seguente programma con Visual Studio 10, ricevo molti errori di compilazione:problema con std :: make_tuple in 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; 
} 

Errore 1 Errore C2664: 'std :: basic_string < _Elem, _Traits, _Ax> :: basic_string (const std :: basic_string < _Elem, _Traits, _Ax> &) ': impossibile convertire il parametro 1 da' const key_t 'a' const std :: basic_string < _Elem, _Traits, _Ax > & 'c: \ programmi (x86) \ microsoft visual studio 10.0 \ vc \ include \ tuple 127 1 tupla

proveniente dalla linea:

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

cosa strana è, come almeno dal mio punto di vista, se cambio queste righe:

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

a

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

la compila il programma. Quindi la mia domanda è, naturalmente, perché? Credo che abbia qualcosa a che fare con make_tuple e spostare la semantica - ma non capisco che cosa ..

risposta

4

A quanto pare l'errore viene infatti dalla linea the_map[k] = "the value";

Quando si utilizza l'operatore [] su una mappa, la libreria tenta di creare un oggetto std::pair<Key,Value>. Nel tuo caso, questo diventa std::pair<std::tuple<std::string,std::string>,std::string>.

Tuttavia, se si utilizza una variabile intermedia k, il costruttore di std :: coppia che si chiama è: (copia-incollato dalla lib di serie)

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

Questo costruttore sta cercando di fare una copia di il tuo key_t. Sfortunatamente, l'implementazione tuple di MSVC++ è al momento buggata e la copia non riesce a compilare (vedi anche questo: C++0x : are tuples of tuples allowed?)

Posso diagnosticare di più, perché questa implementazione non è solo buggata ma anche molto complicata.

Le tuple di Boost dovrebbero funzionare ma non dispongono di un operatore <, quindi non è possibile utilizzarle.

La soluzione "migliore" per il momento è quello di scrivere the_map.insert(std::make_pair(k, "the value"));

+0

Grazie - funziona e il mio codice originale sembrerà a posto con la tua correzione. – baardk

+0

Nota che puoi anche scrivere 'the_map [std :: move (k)] =" il valore "' ma questo "distruggerà" la tua variabile 'k' (guarda alcuni articoli sulla semantica del movimento se non vedi cosa Intendo per distruggere). – Tomaka17

+0

Bello. Ho postato il problema su alcuni siti di MS Connect, in modo che possano controllare se si tratta di un bug o di cosa. – baardk

2

Questo appare come un bug in VS10, per qualche motivo si sta cercando di lanciare il tipo di chiave per il tipo di valore.

Anche questa versione semplificata non funziona.

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 i seguenti: C2440

errore: 'inizializzazione': non può convertire da 'std :: tr1 const :: tuple < _Arg0, _Arg1>' a 'int'

+0

Ah, bella semplificazione. – baardk

Problemi correlati