首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11中的高阶函数

C++11中的高阶函数
EN

Stack Overflow用户
提问于 2013-03-17 15:21:44
回答 3查看 7.9K关注 0票数 10

我正在尝试使用C++11中新的匿名函数来编写一个通用的折叠函数,下面是我所拥有的:

代码语言:javascript
复制
template<typename T>
T foldl(std::function<T(T,T)> f, T initial, std::vector<T> items) {
    T accum = initial;
    for(typename std::vector<T>::iterator it = items.begin(); it != items.end(); ++it) {
        accum = f(accum, (*it));
    }
    return accum;
}

下面尝试使用它:

代码语言:javascript
复制
std::vector<int> arr;
arr.assign(8, 2);
foldl([] (int x, int y) -> int { return x * y; }, 1, arr);

导致错误:

代码语言:javascript
复制
main.cpp:44:61: error: no matching function for call to 'foldl(main(int, char**)::<lambda(int, int)>, int, std::vector<int>&)'
main.cpp:44:61: note: candidate is:
main.cpp:20:3: note: template<class T> T foldl(std::function<T(T, T)>, T, std::vector<T>)
main.cpp:20:3: note:   template argument deduction/substitution failed:
main.cpp:44:61: note:   'main(int, char**)::<lambda(int, int)>' is not derived from 'std::function<T(T, T)>'

在我看来,使用std::function并不是定义f类型的正确方式。我怎样才能纠正这个错误呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-17 15:31:21

你的代码不是很通用。不需要functionvector或任何类似的东西。通常,在C++中,函数将位于参数列表的末尾(对于lambda尤其重要,因为它们可以很大)。

所以最好(也就是更标准的)写成这样:

代码语言:javascript
复制
template<typename Range, typename Accum>
typename Range::value_type foldl(const Range &items, const typename Range::value_type &initial, Accum f)
{
    typename Range::value_type accum = initial;
    for(const auto &val : items) {
        accum = f(accum, val);
    }

    return accum;
}

或者你可以只使用use std::accumulate,它可以做同样的事情。

票数 15
EN

Stack Overflow用户

发布于 2013-03-17 15:25:38

我不确定为什么这个模板失败了,但是切换到对函数使用模板参数而不是std::function<>似乎工作得很好。

代码语言:javascript
复制
template<typename T, typename F>
T foldl(F f, T initial, std::vector<T> items) {
票数 4
EN

Stack Overflow用户

发布于 2013-03-18 08:03:13

如果您只需先将其转换为std::function,然后再使用它,它将会起作用:

代码语言:javascript
复制
std::vector<int> arr;
arr.assign(8, 2);
std::function<int(int,int)> f = [] (int x, int y) -> int { return x * y; };
foldl(f, 1, arr);

问题是lambda是一种与std::function不同的类型。每个lambda都是一个单独的类型。尽管lambda (和所有其他函数对象)可以通过适当的类型参数转换为std::function,但编译器不知道T的哪个模板参数会使其可转换。(我们碰巧知道T = int可以工作,但是没有通用的方法来解决这个问题。)所以它不能编译它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15458483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档