0

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.

dhairya
  • 431
  • 1
  • 4
  • 12
  • 1
    You could avoid the problem by using a `std::vector` instead. – Ted Lyngmo Aug 08 '19 at 10:30
  • 1
    `copy` takes two iterators, not two elements. Use `BCobj + i + 1, BCobj + i` instead of `BCobj[i+1], BCobj[i]`. – L. F. Aug 08 '19 at 10:32
  • `int size = 10;struct BigClass::Astruct BCobj[size];` -- This is not valid C++ code. Arrays in C++ have their sizes denoted by constant expressions, not variables. Use `std::vector` instead -- that's what it is designed for, dynamic array uses. – PaulMcKenzie Aug 08 '19 at 12:28

2 Answers2

3

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))
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
0

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.

Community
  • 1
  • 1
Chef Gladiator
  • 902
  • 11
  • 23