Problem with std::make_tuple in C++0x
Tying to compile the following program with Visual Studio 10, I get lot of compile errors:
#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;
}
Error 1 error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'const key_t' to 'const std::basic_string<_Elem,_Traits,_Ax> &' c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple 127 1 tuple
Coming from the line:
std::cout << i->second << std::endl;
Strange thing is, as least from my point of view, if I change these lines:
auto k = std::make_tuple("one", "two");
the_map[k] = "the value";
to
the_map[std::make_tuple("one", "two")] = "p";
the program compiles. So my question is of course why? I guess it has something to do with make_tuple and move semantics - but I do not understand what..
Apparently the error comes in fact from the line the_map[k] = "the value";
When you use the [] operator on a map, the library tries to create a std::pair<Key,Value>
object. In your case, this becomes std::pair<std::tuple<std::string,std::string>,std::string>
.
However if you use an intermediate variable k
, the constructor of std::pair which is called is: (copy-pasted from the standard lib)
_Pair_base(const _Ty1x& _Val1, _Ty2x&& _Val2)
: first(_Val1), second(_STD move(_Val2))
{ // construct from specified values
}
This constructor is trying to make a copy of your key_t. Unfortunatly, the tuple implementation of MSVC++ is bugged at the moment and the copy fails to compile (see also this: C++0x : are tuples of tuples allowed?)
I can diagnosize more, because this implementation is not only bugged but also very complicated.
Boost's tuples should work but don't have an < operator, so you can't use them.
The "best" solution for the moment is to write the_map.insert(std::make_pair(k, "the value"));
This looks like a bug in VS10, for some reason it's trying to cast the key type to the value type.
This simplified version also fails.
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;
Produces the following:
error C2440: 'initializing' : cannot convert from 'const std::tr1::tuple<_Arg0,_Arg1>' to 'int'
精彩评论