出于练习目的,我想创建一个类似于以下内容的函数std::transform()
:
template<class Tin, class Tout>
std::vector<Tout> map( const std::vector<Tin>& in,
const std::function<Tout(const Tin&)>& mapper ) {
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( in ) );
}
return ret;
}
我打算将其按如下方式使用:
std::vector<Bar> bars /* = ... */;
std::vector<Foo> foos = map( bars, []( const Bar& bar ) { return bar.to_foo(); } );
但是,我得到了函数调用的未定义引用。我的map()
功能的正确签名是什么?
*更新:*这是实际的错误消息(Bar = std::string
,Foo = IPv6
(自己的类))
config.cc:98:61: error: no matching function for call to ‘map(const std::vector<IPv6>&, InterfaceConfig::set_ip6(const std::vector<IPv6>&)::<lambda(const IPv6&)>)’
config.cc:98:61: note: candidate is:
utils.h:38:31: note: template<class Tin, class Tout> std::vector<Tout> utils::map(const std::vector<Tin>&, const std::function<Tout(const Tin&)>&)
这就是调用:std :: vector字符串= utils :: map(ips,[](const IPv6&ip){return ip.to_string();});
您的代码中有两件事是行不通的。
Template
。例如,Microsoft上的标准库似乎使用此方法std::for_each
。和 :
当函数模板具有不能从参数推断出的返回类型时,或者当函数模板没有任何参数时,编译器将无法推断出该类型。此函数将需要模板类型参数说明。
看一下这个例子:
template<class Tout, class Tin, class Fun>
// ^^^^^^^^^^^
// Note that I changed the order of the types
std::vector<Tout> map( const std::vector<Tin>& in,
Fun mapper ) {
// ^^^^^^^^^^
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map<float>( bars, []( int ) { return 1.0f; } );
// ^^^^^^^ Specify the type Tout
system( "pause" );
return 0;
}
编辑 :
就像注释中所说的那样,我们可以使用decltype
而std::decay
不必显式指定函数的结果:
template<class Tin, class Fun> // no Tout
// ^^^^^^^^^^^
auto map( const std::vector<Tin>& in, Fun mapper )
//^^^^ ^^^^^^^^^^
-> std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > {
std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map( bars, []( int ) { return 1.0f; } );
// No specification
system( "pause" );
return 0;
}
让我们解释一下。
首先,我们将使用最新指定的返回类型语法。这将使我们能够在返回类型规范中使用参数名称。我们以开始auto
,并将返回类型指定放在参数之后,使用->
。
我们将使用decltype
因为decltype类型说明符会产生指定表达式的类型。在我们的案例中这将非常有用。例如,要获取我们传入参数的函数的类型,它就是decltype( f( someArg ) )
。
让我们陈述一下我们想要什么:函数的返回类型应该是传入参数right的函数的返回类型的向量?这样我们就可以回来std::vector< decltype( mapper( in.front() ) )>
了!(为什么in.front()
?我们必须将参数传递给函数以具有有效的表达式。)
但是,这里又有一个问题:std::vector
不允许引用。为了确定对我们来说这不是问题,我们将使用std::decay
元函数将左值到右值,数组到指针和函数到指针的隐式转换应用于类型T,删除cv- qualifiers,删除引用,并将结果类型定义为成员typedef类型。。也就是说,如果函数返回的内容类似const Foo&
它将以结尾Foo
。
所有这些的结果:std::vector< typename std::decay< decltype( mapper( in.front() ) )>::type >
。
您必须在函数的开头再次重复此表达式,以声明将要返回的变量。
一些有用的参考资料:
这不容易解释,我希望我的解释是可以理解的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句