使用transform和lambdas的简单程序不起作用

时间:2013-06-08 15:29:12

标签: c++ c++11

我收到了这些错误。为什么呢?

<子>

  

在/usr/include/c++/4.7/algorithm:63:0中包含的文件中,                    来自prog.cpp:2:   /usr/include/c++/4.7/bits/stl_algo.h:实例化'_Oite std :: transform(_IIter,_IIter,_Oter,_UnaryOperation)[with _IIter = __gnu_cxx :: __ normal_iterator&gt ;; _OIter = std :: back_insert_iterator&gt ;; _UnaryOperation = main()::]':   prog.cpp:10:98:从这里需要   /usr/include/c++/4.7/bits/stl_algo.h:4951:2:错误:无法匹配调用'(main()::)(int&amp;)'   prog.cpp:10:64:注意:候选人是:   在/usr/include/c++/4.7/algorithm:63:0中包含的文件中,                    来自prog.cpp:2:   /usr/include/c++/4.7/bits/stl_algo.h:4951:2:注意:int(*)(int,int)   /usr/include/c++/4.7/bits/stl_algo.h:4951:2:注意:候选人需要3个参数,2个提供   prog.cpp:10:79:注意:main()::   prog.cpp:10:79:注意:候选人需要2个参数,1个提供   

#include <algorithm>
#include <vector>

int main()
{
    std::vector<int> v {1, 2, 3, 4, 5, 6};
    std::vector<int> r;

    std::transform(v.begin(), v.end(), std::back_inserter(r), [] (int a, int b) { return a + b; });
}

此代码应该将每对数字相加并将其放入r向量中,但它不起作用。那是为什么?

1 个答案:

答案 0 :(得分:3)

您选择了transform()的重载,它适用于单个范围 - 因此需要提供一元仿函数作为最后一个参数。

如果您想要的是两个范围(可能是相同范围的两个“副本”),那么您应该这样做:

std::transform(v.begin(), v.end(), v.begin(), 
//                                 ^^^^^^^^^
    std::back_inserter(r), [] (int a, int b) { return a + b; });

所以这是完整的代码:

#include <algorithm>
#include <vector>

int main()
{
    std::vector<int> v {1, 2, 3, 4, 5, 6};
    std::vector<int> r;

    std::transform(v.begin(), v.end(), v.begin(),
        std::back_inserter(r), [] (int a, int b) { return a + b; });
}

这是一个编译live example

但是,除非您只是想练习在两个输入范围上运行的std::transform()的重载,否则您可以按照Konrad Rudolph's advice from the comments进行操作,并写下:

std::transform(v.begin(), v.end(), 
    std::back_inserter(r), [] (int a) { return a * 2; });

相反,如果您想要执行每对连续元素的总和并使用类似转换的方法将结果存储在r向量中,那么您可以求助于Boost.Range,并写入类似的东西:

#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>

// ...

namespace rng = boost::adaptors;

// This will fill r with values { 3, 7, 11 }
boost::transform(
    v | rng::strided(2),
    std::make_pair(v.begin() + 1, v.end()) | rng::strided(2),
    std::back_inserter(r),
    [] (int a, int b) { return a + b; });

这是live example

另外,as pointed out by NeelBasu in the comments,而不是使用std::make_pair()来定义第二个范围,您可以根据sliced范围适配器编写更具表现力(且紧凑)的版本:

boost::transform(
    v | rng::strided(2),
    v | rng::sliced(1, v.size()) | rng::strided(2),
    std::back_inserter(r),
    [] (int a, int b) { return a + b; });