[英]Why can't I use std::get<0> in std::transform?
In trying to compile the following code which would copy a map
s keys to a vector
: 在尝试编译以下代码时,会将
map
s键复制到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: VS2013无法区分哪个
get
是有意的,但这个更简单的用法可以正常工作:
vs.push_back(get<0>(*mss.begin()));
Specifying get<0, string, string>
didn't help. 指定
get<0, string, string>
没有帮助。 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. std::get
有很多重载,其中每个都是一个函数模板本身,因此编译器无法在你请求其中一个地址的调用站点分辨出你想要的那个。 If you insist on using std::get
, you'd need to use static_cast
: 如果你坚持使用
std::get
,你需要使用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. 只要
static_cast
中的类型与作为参数给出的可能的函数模板的特化的声明匹配,这将起作用。 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. 此外,您不应尝试显式指定函数模板的模板参数,如
get<0, string, string>
等。这就是模板参数推导机制的用途。 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 : 一个更好的选择是使用lambda表达式 :
transform(mss.begin(), mss.end(), back_inserter(vs),
[](map<string, string>::value_type& p){ return p.first; });
or a generic lambda expression (C++14): 或一般的lambda表达式 (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: 或者
std::mem_fn
,它将其参数绑定到指向数据成员或成员函数的给定指针:
#include <functional>
transform(mss.begin(), mss.end(), back_inserter(vs),
mem_fn(&map<string, string>::value_type::first));
The first member of the pair stored in map is const-qualified. 存储在map中的对的第一个成员是const限定的。 So technically you need
所以技术上你需要
get<0, const string, string>
But that does not limit the list of candidates to one unambiguous overload, since get
is available in at least two versions: for const reference argument and for non-const reference argument. 但是这并不会将候选列表限制为一个明确的重载,因为
get
至少有两个版本:const参数参数和非const参考参数。
You can choose one by using a cast 您可以使用演员表选择一个
const string &(*g)(const pair<const string, string> &) =
get<0, const string, string>;
or 要么
typedef map<string, string> Map;
const Map::key_type &(*g)(const Map::value_type &) =
get<0, const Map::key_type, Map::mapped_type>;
and then do 然后呢
transform(mss.begin(), mss.end(), back_inserter(vs), g);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.