Custom inserter for std::copy

后端 未结 2 1458
心在旅途
心在旅途 2020-12-16 21:03

Given a std::vector which holds objects of MyClass. How can I create another vector which holds just data of one member of MyClass using std::copy?

相关标签:
2条回答
  • 2020-12-16 21:27

    You want to use std::transform not std::copy and std::bind to bind to a pointer to a member variable:

    #include <algorithm>
    #include <iterator>
    #include <vector>
    #include <iostream>
    #include <functional>
    
    struct foo {
      int a;
    };
    
    int main() {
      const std::vector<foo> f = {{0},{1},{2}};
      std::vector<int> out;
    
      out.reserve(f.size());
      std::transform(f.begin(), f.end(), std::back_inserter(out), 
                     std::bind(&foo::a, std::placeholders::_1));
    
      // Print to prove it worked:
      std::copy(out.begin(), out.end(), std::ostream_iterator<int>(std::cout, "\n"));
    }
    

    My example is C++11, but if you skip the handy vector initalization and use boost::bind instead this works just as well without C++11.

    0 讨论(0)
  • 2020-12-16 21:44

    Use std::transform for that.

    std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2),
                   [](const MyClass& cls) { return cls.a; });
    

    (If you can't use C++11, you could make a function object yourself:

    struct AGetter { int operator()(const MyClass& cls) const { return cls.a; } };
    
    std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), AGetter());
    

    or use std::tr1::bind if you can use TR1:

    std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2),
                   std::tr1::bind(&MyClass::a, std::tr1::placeholders::_1));
    

    BTW, as @Nawaz commented below, do a .reserve() to prevent unnecessary reallocation during the copy.

    vec2.reserve(vec1.size());
    std::transform(...);
    
    0 讨论(0)
提交回复
热议问题