c++11 - Function taking lambda expression -
for practicing purposes wanted create function similar 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; }
and intended use follows:
std::vector<bar> bars /* = ... */; std::vector<foo> foos = map( bars, []( const bar& bar ) { return bar.to_foo(); } );
however, undefined references function call. correct signature map()
function?
*update: * here's actual error message (bar = std::string
, foo = ipv6
(own class))
config.cc:98:61: error: no matching function call ‘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&)>&)
and here's call: std::vector strings = utils::map( ips, []( const ipv6& ip ) { return ip.to_string(); } );
there 2 things in code not work.
- first, when passing lambda function argument, suggest using
template
. standard library on microsoft seems use methodstd::for_each
example. and :
when function template has return type, cannot deduced arguments, or when function template doesn't have argument, type cannot deduced compiler. function require template type argument specification.
take @ example :
template<class tout, class tin, class fun> // ^^^^^^^^^^^ // note changed order of 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 type tout system( "pause" ); return 0; }
edit :
like said in comment, can use decltype
, std::decay
not have explicitly specify result of function :
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; }
let's explain little bit.
first use late-specified return type syntax. allow use parameter names in return type specification. start line auto
, put return type specification after parameters using ->
.
we use decltype
because decltype type specifier yields type of specified expression. useful in our case. example type of function passed in parameters, decltype( f( somearg ) )
.
let's state want : return type of function should vector of return type of function passed in argument right ? can return std::vector< decltype( mapper( in.front() ) )>
, that's ! (why in.front()
? have pass parameter function have valid expression.)
but here again, have problem : std::vector
not allow references. not problem us, use std::decay
meta-function applies lvalue-to-rvalue, array-to-pointer, , function-to-pointer implicit conversions type t, removes cv-qualifiers, remove references, , defines resulting type member typedef type.. is, if function returns const foo&
end in foo
.
the result of of : std::vector< typename std::decay< decltype( mapper( in.front() ) )>::type >
.
you have repeat expression again @ beginning of function declare variable return.
some usefull references :
- http://en.cppreference.com/w/cpp/types/decay
- http://en.wikipedia.org/wiki/decltype
- http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html
- http://msdn.microsoft.com/en-us/library/dd537655.aspx
it not easy explain, hope explanations understandable.
Comments
Post a Comment