2010-08-02 5 views
5

Tying pour compiler le programme suivant avec Visual Studio 10, je reçois beaucoup d'erreurs de compilation:problème avec 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; 
} 

Erreur 1 Erreur C2664: « std :: basic_string < _Elem, _Traits, _Ax> :: basic_string (const std :: basic_string < _Elem, _Traits, _Ax> &) ': impossible de convertir le paramètre 1 de' const key_t 'en' const std :: basic_string < _Elem, _Traits, _Ax > & 'c: \ fichiers de programme (x86) \ microsoft studio visuel 10.0 \ vc \ include \ tuple 127 1 tuple

venant de la ligne:

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

Chose étrange est, du moins de mon point de vue, si je change ces lignes:

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

à

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

la programme compile. Donc, ma question est bien sûr pourquoi? Je suppose qu'il a quelque chose à voir avec make_tuple et déplacer la sémantique - mais je ne comprends pas ce que ..

Répondre

4

Apparemment, l'erreur vient en fait de la ligne the_map[k] = "the value";

Lorsque vous utilisez l'opérateur [] sur une carte, la bibliothèque tente de créer un objet std::pair<Key,Value>. Dans votre cas, cela devient std::pair<std::tuple<std::string,std::string>,std::string>.

Toutefois, si vous utilisez une variable intermédiaire k, le constructeur de std :: paire qui est appelée est:

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

(copier-coller de la lib standard) Ce constructeur tente de faire une copie votre key_t. Malheureusement, l'implémentation de MSVC++ est buggée pour le moment et la copie ne compile pas (voir aussi: C++0x : are tuples of tuples allowed?)

Je peux diagnostiquer plus, car cette implémentation est non seulement buggée mais aussi très compliquée.

Les tuples de Boost devraient fonctionner mais n'ont pas d'opérateur <, donc vous ne pouvez pas les utiliser.

La « meilleure » solution pour le moment est d'écrire the_map.insert(std::make_pair(k, "the value"));

+0

Merci - cela fonctionne et mon code d'origine semblera correct avec votre solution. – baardk

+0

Notez que vous pouvez également écrire 'the_map [std :: move (k)] =" la valeur "' mais cela va "détruire" votre variable 'k' (regardez quelques articles sur la sémantique de déplacement si vous ne voyez pas Je veux dire par détruire). – Tomaka17

+0

Nice. J'ai posté le problème sur un site MS Connect, afin qu'ils puissent vérifier s'il s'agit d'un bug ou quoi. – baardk

2

Cela ressemble à un bogue dans VS10, pour une raison quelconque, il essaie de lancer le type de clé du type de valeur.

Cette version simplifiée échoue également.

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; 

produit les éléments suivants:

erreur C2440: 'initialisation': ne peut pas convertir 'const std :: tr1 :: tuple < _Arg0, _Arg1>' à 'int'

+0

Ah, belle simplification. – baardk