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.

3
  • 1
    You could avoid the problem by using a std::vector instead. Commented Aug 8, 2019 at 10:30
  • 1
    copy takes two iterators, not two elements. Use BCobj + i + 1, BCobj + i instead of BCobj[i+1], BCobj[i]. Commented Aug 8, 2019 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. Commented Aug 8, 2019 at 12:28

2 Answers 2

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))
Sign up to request clarification or add additional context in comments.

2 Comments

copy( begin(BCobj), end(BCobj), begin(second_BCobj))
It will be even better if you take ADL into consideration when looking up begin and end. (Or use ranges::begin and ranges::end in C++20)
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.