【问题标题】:Simple program using transform and lambdas isn't working使用转换和 lambdas 的简单程序不起作用
【发布时间】:2013-06-04 18:14:16
【问题描述】:

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

在 /usr/include/c++/4.7/algorithm:63:0 包含的文件中, 来自 prog.cpp:2: /usr/include/c++/4.7/bits/stl_algo.h:在'_OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation) 的实例化中 [with _IIter = __gnu_cxx::__normal_iterator >; _OIter = std::back_insert_iterator >; _UnaryOperation = main()::]': prog.cpp:10:98: 从这里需要 /usr/include/c++/4.7/bits/stl_algo.h:4951:2: 错误:不匹配调用‘(main()::) (int&)’ 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 向量中,但它不起作用。这是为什么呢?

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    您选择了在单个范围内工作的 transform() 的重载 - 因此希望提供一个 unary 函子作为最后一个参数。

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

    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; });
    

    【讨论】:

    • 不确定这是否是 OP 真正想要的,因为这相当于带有 lambda [](int a){return 2*a;} “每对数字”的一元版本听起来更像是 OP 想要枚举所有成对数字(这将真的不是transform 的工作。
    • @KonradRudolph:重新阅读答案后,我认为您是对的。将再次编辑
    • 不,你所拥有的一切都很好。谢谢。
    • @MemyselfandI:嗯,但我所展示的并没有将每对连续的元素加起来。那是你想做的吗?或许你可以考虑在这种情况下使用 Boost.Range
    猜你喜欢
    • 2015-10-06
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    相关资源
    最近更新 更多