In trying to compile the following code which would copy a map
s keys to a vector
:
map<string, string> mss;
vector<string> vs;
transform(mss.begin(), mss.end(), back_inserter(vs), get<0>);
VS2013 can't distinguish which get
is intended but this simpler usage works just fine:
vs.push_back(get<0>(*mss.begin()));
Specifying get<0, string, string>
didn't help. What am I missing?
There are many overloads of std::get
, where, in addition, each is a function template itself, therefore the compiler can't tell which one you want at the call site where you request for the address of one of them. If you insist on using std::get
, you'd need to use static_cast
:
transform(mss.begin(), mss.end(), back_inserter(vs),
static_cast<const map<string, string>::key_type&
(*)(map<string, string>::value_type&)>(std::get<0>)
);
Which will work as long as the type in static_cast
matches the declaration of a possible function template's specialization given as the argument. Also, you shoudn't try to explicitly specify the template arguments of function templates like get<0, string, string>
etc. - this is what the template argument deduction mechanism is for. Not only is the syntax ugly, but there can be other overloads added in the future breaking your compilation.
A much better alternative is to use a lambda expression:
transform(mss.begin(), mss.end(), back_inserter(vs),
[](map<string, string>::value_type& p){ return p.first; });
or a generic lambda expression (C++14):
transform(mss.begin(), mss.end(), back_inserter(vs),
[](auto& p){ return p.first; }); // or `return std::get<0>(p);`
or std::mem_fn
which binds its argument to a given pointer to a data member or a member function:
#include <functional>
transform(mss.begin(), mss.end(), back_inserter(vs),
mem_fn(&map<string, string>::value_type::first));