Using c++ std::copy on an array of structure

3.2k Views Asked by At

I want to use std::copy to copy an existing array of structures to new one. A regular option is fine with '''local_copy()'''. I want to know the procedure to use std::copy for such case described below -

I tried the code and get following error at compile time

#include <iostream>

class BigClass{
public:
struct Astruct{
    double x[2], v[2];
    int rank;
}one_struct;

};

void allocate(struct BigClass::Astruct& one_struct, int i)
{
one_struct.x[0] = 1.1;
one_struct.x[1] = 1.2;
one_struct.v[0] = 2.1;
one_struct.v[1] = 2.2;
one_struct.rank = i;
}

void local_copy(struct BigClass::Astruct& dest, struct BigClass::Astruct& source)
{
dest.x[0] = source.x[0];
dest.x[1] = source.x[1];
dest.v[0] = source.v[0];
dest.v[1] = source.v[1];
dest.rank = source.rank;
}

void print(struct BigClass::Astruct one_struct)
{
std::cout << one_struct.rank << " " << one_struct.x[0] << " " << one_struct.x[1] << " " << one_struct.v[0] << " " << one_struct.v[1] << "\n";
}



int main(int argc, char *argv[]) {

int size = 10;
struct BigClass::Astruct BCobj[size];
for(int i = 0; i < size; i++) allocate(BCobj[i], i);
for(int i = 0; i < size; i++) print(BCobj[i]);

struct BigClass::Astruct second_BCobj[size];
//for(int i = 0; i < size; i++) local_copy(second_BCobj[i], BCobj[i]); // this works
for(int i = 0; i < size; i++) std::copy(BCobj[i+1], BCobj[i], second_BCobj[i]); // not working

for(int i = 0; i < size; i++) print(BCobj[i]);

}

The compile time error is following -

/usr/include/c++/7/bits/stl_algobase.h:377:57: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
   typedef typename iterator_traits<_II>::value_type _ValueTypeI;
                                                     ^~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:378:57: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
   typedef typename iterator_traits<_OI>::value_type _ValueTypeO;
                                                     ^~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:379:64: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<BigClass::Astruct>’
   typedef typename iterator_traits<_II>::iterator_category _Category;
                                                            ^~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:383:9: error: no type named ‘value_type’ in ‘struct std::iterator_traits<BigClass::Astruct>’
   const bool __simple = (__is_trivial(_ValueTypeI)
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~
                   && __is_pointer<_II>::__value
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                   && __is_pointer<_OI>::__value
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     && __are_same<_ValueTypeI, _ValueTypeO>::__value);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/7/bits/stl_algobase.h:386:44: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<BigClass::Astruct>’
   return std::__copy_move<_IsMove, __simple,
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    _Category>::__copy_m(__first, __last, __result);
                        ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~

Some examples for vectors and int datatypes are available. Could anyone elaborate the appropriate sequence for std::copy for this kind of code structure? Thanks.

2

There are 2 best solutions below

2
On BEST ANSWER

std::copy is used instead of for loop, not with one.

std::copy(BCobj, BCobj + size, second_BCobj);

is essentially the same as

for(int i = 0; i < size; ++i) {
    second_BCobj[i] = BCobj[i];
}

Also, don't forget to #include <algorithm> for std::copy


Explanation of arguments for std::copy:

std::copy takes as arguments 2 arguments of type matching InputIterator requirements and single argument of type OutputIteretor. Fortunately, pointers match these requirements, so we can use them directly. And because array name is interpreted as a pointer to its first element, we can pass it directly as argument to std::sort


Better version as suggested by Chef Gladiator:

std::copy(std::begin(BCobj), std::end(BCobj), std::begin(second_BCobj))
0
On

Welcome to Stack Overflow. You have presented your full code. Please next time also describe the development environment you are building in. Even better, try to present operating system agnostic and compiler agnostic, standard C++ code.

This is C++ forum, so we like to use standard C++ here. Your code is rewritten bellow using std::array. That makes it simple. Please study and enjoy the standard C++.

  #include <array>
  #include <iostream>
  #include <algorithm>

  namespace stack_overflow {

      using namespace std;

      struct BigClass final {
          struct Astruct final {
              double x[2], v[2];
              int rank;
          }one_struct;

          friend ostream& operator << (ostream& os, Astruct const & one_struct)
          {
              return os << one_struct.rank << " " << one_struct.x[0] << " "
                  << one_struct.x[1] << " " << one_struct.v[0] << " "
                  << one_struct.v[1] ;
          }
      };

      constexpr int size = 10;
      using bcobj_arr = std::array<BigClass::Astruct, size>;

      void populate( bcobj_arr& bcobjects_)
      {
          int j{ 0 };
          for (auto& one_struct : bcobjects_) {
              one_struct.x[0] = 1.1;
              one_struct.x[1] = 1.2;
              one_struct.v[0] = 2.1;
              one_struct.v[1] = 2.2;
              one_struct.rank = j++;
          }
      }

      void print(const char prompt[BUFSIZ], bcobj_arr const & bcobjects_ )
      {
          cout << "\n\n" << prompt << "\n\n" ;
          for (auto& one_struct : bcobjects_) {
              cout << one_struct << "\n";
          }
      }

      bool test (int argc, const char* argv[]) 
      {
          bcobj_arr BCobj;
          populate(BCobj);
          print("BCobj", BCobj);
            // std::array instances can be copied
            bcobj_arr second_BCobj = BCobj ;
          print("second_BCobj", second_BCobj);
          return true;
      }
  }

 int main(const int argc, const char * argv[])
 {
  stack_overflow::test(argc, argv);
  return 42;
 }

Code is not commented at all. I assume you have a lot of questions, please do ask, in the comments bellow. I will try and answer them all by pointing you to the relevant documentation on-line.