gpt4 book ai didi

c++ - 当std::function or lambda functions are involved时C++ 11不能推断类型

转载 作者:行者123 更新时间:2023-12-02 10:56:39 26 4
gpt4 key购买 nike

当我定义此功能时,

template<class A>
set<A> test(const set<A>& input) {
return input;
}

我可以在代码的其他地方使用 test(mySet)来调用它,而不必显式定义模板类型。但是,当我使用以下功能时:
template<class A>
set<A> filter(const set<A>& input,function<bool(A)> compare) {
set<A> ret;
for(auto it = input.begin(); it != input.end(); it++) {
if(compare(*it)) {
ret.insert(*it);
}
}
return ret;
}

当我使用 filter(mySet,[](int i) { return i%2==0; });调用此函数时
我收到以下错误:

error: no matching function for call to ‘filter(std::set&, main()::)’



但是,所有这些版本都可以使用:
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;}));

当我将lambda函数直接放置在表达式中而不直接创建 std::function时,为什么c++ 11无法猜测模板类型?

编辑:

根据Luc Danton在评论中的建议,这是我之前拥有的功能的替代方法,不需要显式传递模板。
template<class A,class CompareFunction>
set<A> filter(const set<A>& input,CompareFunction compare) {
set<A> ret;
for(auto it = input.begin(); it != input.end(); it++) {
if(compare(*it)) {
ret.insert(*it);
}
}
return ret;
}

无需模板即可通过 set<int> result = filter(myIntSet,[](int i) { i % 2 == 0; });调用它。

编译器甚至可以使用new decltype关键字和新函数return type语法在某种程度上猜测返回类型。这是一个示例,该示例使用一个过滤功能和一个根据值生成键的功能将集合转换为 map :
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 it = input.begin(); it != input.end(); it++) {
if(compare(*it)) {
ret[index(*it)] = *it;
}
}
return ret;
}

也可以不直接使用模板而调用它,例如
map<string,int> s = filter(myIntSet,[](int i) { return i%2==0; },[](int i) { return toString(i); });

最佳答案

问题在于lambda的性质。它们是根据标准具有固定属性集的函数对象,但不是函数。该标准确定可以将lambda转换为带有确切类型的参数的std::function<>,如果没有状态,则将其转换为函数指针。

但这并不意味着lambda是std::function也不是函数指针。它们是实现operator()的唯一类型。

另一方面,类型推导只能推断出确切的类型,不进行任何转换(const/volatile限定除外)。因为lambda不是std::function,所以编译器无法推断出调用中的类型:filter(mySet,[](int i) { return i%2==0; });是任何std::function<>实例化。

与其他示例一样,在第一个示例中,您将lambda转换为函数类型,然后将其传递。编译器可以在此处推导类型,如在第三个示例中,std::function是相同类型的右值(临时)。

如果您向模板(第二个工作示例)提供实例化类型int,则推论不起作用,编译器将使用该类型,然后将lambda转换为适当的类型。

关于c++ - 当std::function or lambda functions are involved时C++ 11不能推断类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61708020/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com