当我定义此功能时,

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; });调用此函数时
我收到以下错误:



但是,所有这些版本都可以使用:
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或lambda函数时,C++ 11不会推断类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31118987/

10-11 22:51
查看更多