c++ - C++11 does not deduce type when std::function or lambda functions are involved -
when define function,
template<class a> set<a> test(const set<a>& input) { return input; }
i can call using test(myset)
elsewhere in code without having explicitly define template type. however, when use following function:
template<class a> set<a> filter(const set<a>& input,function<bool(a)> compare) { set<a> ret; for(auto = input.begin(); != input.end(); it++) { if(compare(*it)) { ret.insert(*it); } } return ret; }
when call function using filter(myset,[](int i) { return i%2==0; });
following error:
error: no matching function call ‘filter(std::set<int>&, main()::<lambda(int)>)’
however, of these versions do work:
std::function<bool(int)> func = [](int i) { return i%2 ==0; }; set<int> mynewset = filter(myset,func); set<int> mynewset = filter<int>(myset,[](int i) { return i%2==0; }); set<int> mynewset = filter(myset,function<bool(int)>([](int i){return i%2==0;}));
why c++11 unable guess template type when put lambda function directly inside expression without directly creating std::function
?
edit:
per advice of luc danton in comments, here alternative function had earlier not need templates passed explicitly.
template<class a,class comparefunction> set<a> filter(const set<a>& input,comparefunction compare) { set<a> ret; for(auto = input.begin(); != input.end(); it++) { if(compare(*it)) { ret.insert(*it); } } return ret; }
this can called set<int> result = filter(myintset,[](int i) { % 2 == 0; });
without needing template.
the compiler can guess return types extent, using new decltype keyword , using new function return type syntax. here example converts set map, using 1 filtering function , 1 function generates keys based on values:
template<class value,class comparetype,class indextype> auto filter(const set<value>& input,comparetype compare,indextype index) -> map<decltype(index(*(input.begin()))),value> { map<decltype(index(*(input.begin()))),value> ret; for(auto = input.begin(); != input.end(); it++) { if(compare(*it)) { ret[index(*it)] = *it; } } return ret; }
it can called without using template directly, as
map<string,int> s = filter(myintset,[](int i) { return i%2==0; },[](int i) { return tostring(i); });
the issue on nature of lambdas. function objects fixed set of properties according standard, not function. standard determines lambdas can converted std::function<>
exact types of arguments and, if have no state, function pointers.
but not mean lambda std::function
nor function pointer. unique types implementing operator()
.
type deduction, on other hand, deduce exact types, no conversions (other const/volatile qualifications). because lambda not std::function
compiler cannot deduce type in call: filter(myset,[](int i) { return i%2==0; });
std::function<>
instantiation.
as of other examples, in first 1 convert lambda function type, , pass that. compiler can deduce type there, in third example std::function
rvalue (temporary) of same type.
if provide instantiating type int
template, second working example, deduction not come play compiler use type , convert lambda appropriate type.
Comments
Post a Comment