【问题标题】:C++ Using std::transform on a vector of structuresC++ 在结构向量上使用 std::transform
【发布时间】:2014-02-27 03:47:45
【问题描述】:

我有一个带有structC++ 应用程序,它看起来像:

struct test_struc {
    std::string name;
    int x;
    int y;
    std::vector<int> data;
};

我想根据结构中的data 元素使用线条转换两个std::vector&lt;test_struc&gt;。到目前为止,我有代码:

std::vector<test_struc> first = <from somewhere else>;
std::vector<test_struc> second = <from somewhere else>;

std::vector<int> result;
std::transform (second.begin(), second.end(), first.begin(), result.begin(), op_xor);

op_xor 在哪里:

int op_xor (int &i,
            int &j) {
    return  i^j;
}

如果firstsecondint 的向量,这很有效,但由于它们不是,我不知道如何告诉代码使用test_strucdata 元素作为参数到std::transform

我是不是找错树了?或者有没有办法做到这一点?

【问题讨论】:

  • 您知道,已经有en.cppreference.com/w/cpp/utility/functional/bit_xor。而 IIRC,你不能在 transform 调用中修改东西,所以通过非常量引用是不好的。如果test_struct 具有按位异或的逻辑定义,则重载运算符。如果没有,请让您的函子获取这些对象并对适当的成员进行操作。

标签: c++ vector struct transform


【解决方案1】:

请注意,至少对于现代编译器,您可能希望将操作实现为 lambda 表达式,所以它看起来像:

std::transform(second.begin(), second.end(), 
               first.begin(),
               std::back_inserter(result),
               [](test_struct const &a, test_struct const &b) { 
                   return a.y ^ b.y; 
               });

次要问题:事实上,你有 UB,当result 的大小为 0 时,你尝试通过result.begin() 写入。你可以像上面那样使用back_inserter,或者你可以定义result 来初始化它大小为second.size()

【讨论】:

    【解决方案2】:

    你的二元仿函数必须有两个test_structs:

    int op_xor (const test_struct& i,
                const test_struct& j) 
    {
        return  42; // replace wit your desired logic.
    }
    

    不清楚你到底想让函子做什么,但它应该在 test_structs 上运行并返回一个 int。

    【讨论】:

    • 这比我想的要简单得多!谢谢!只要允许,我就会接受。
    【解决方案3】:

    或者使用 lambda。 并记住其他向量的大小必须相同或大于“秒”

      result.resize(second.size());
        std::transform(second.begin(), second.end(), first.begin(), result.begin(),
     [](test_struct & one, test_struct & two){ return one.x ^ two.x; });
    

    但是 Jerry 的 back_inserter 示例更好

    【讨论】:

      【解决方案4】:

      您也可以使用 boost::transform 和 boost phoenix lambdas 来做到这一点:

      #include <boost/range/algorithm.hpp>
      #include <boost/phoenix.hpp>
      
      using boost::phoenix::arg_names::arg1;
      using boost::phoenix::arg_names::arg2;
      
      boost::transform(second, first, std::back_inserter(result), (&arg1)->*&test_struc::x ^ (&arg2)->*&test_struc::x);
      

      boost::transform 的第一个和第二个参数是范围,所以你不必在这里写second.begin(), second.end(), first.begin()

      【讨论】:

        猜你喜欢
        • 2022-06-22
        • 2016-03-01
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        • 2011-08-08
        • 2021-09-22
        • 1970-01-01
        相关资源
        最近更新 更多