6

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..

2 Answers 2

6

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"));

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks - it works and my original code will look okay with your fix.
Note that you can also write the_map[std::move(k)] = "the value" but this will "destroy" your k variable (look at some articles about move semantics if you don't see what I mean by destroy).
Nice. I posted the problem on some MS connect site, so they can check if it is a bug or what.
2

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.