简体   繁体   中英

Assigning multi-dimensional vectors with different types

Suppose I have a std::vector<std::vector<double>> d and want to assign it to a std::vector<std::vector<int>> i ; the best I could come up with was:

#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<vector<double>> d = { {1.0, 2.0}, {3.0, 4.0} };
    vector<vector<int>>    i;

    for_each(begin(d), end(d), [&i](vector<double> &x) {
            i.emplace_back(begin(x), end(x));
        }
    );

    return 0;
}

If both vectors were using the same type internally, I could just use the assignment operator (see C++ copying multidimensional vector ):

i = d;

If the vectors were storing different types internally, but one-dimensional, I could do:

i.assign(begin(d), end(d));

Both of those are really obvious in their intention, which I don't feel is the case with my solution for the multi-dimensional approach. Is there a better way, or an accepted idiom, to do this?

It seems to me that your solution for the 2D vector is a good one. The problem arises when you have to copy a N-dimension vectors of vectors of vectors...

Suppose you want a function copy_multi_vec() that works in a case as follows

   std::vector<std::vector<std::vector<double>>> vvvd
    { { {1.0, 2.0, 3.0}, { 4.0,  5.0,  6.0} },
      { {7.0, 8.0, 9.0}, {10.0, 11.0, 12.0} } };

   std::vector<std::vector<std::vector<int>>> vvvi;

   copy_multi_vec(vvvi, vvvd);

In this case you can use partial template specialization in an helper class; by example

template <typename T1, typename T2>
struct cmvH
 { static void func (T1 & v1, T2 const & v2) { v1 = v2; } };

template <typename T1, typename T2>
struct cmvH<std::vector<T1>, std::vector<T2>>
 {
   static void func (std::vector<T1> & v1, std::vector<T2> const & v2)
    {
      v1.resize( v2.size() );

      std::size_t i { 0U };

      for ( auto const & e2 : v2 )
         cmvH<T1, T2>::func(v1[i++], e2);
    }
 };

template <typename T1, typename T2>
void copy_multi_vec (T1 & v1, T2 const & v2)
 { cmvH<T1, T2>::func(v1, v2); }

or, if you want use the assign() method for the last level, you can define the helper struct as follows

template <typename, typename>
struct cmvH;

template <typename T1, typename T2>
struct cmvH<std::vector<T1>, std::vector<T2>>
 {
   static void func (std::vector<T1> & v1, std::vector<T2> const & v2)
    {
      v1.resize( v2.size() );
      v1.assign( v2.cbegin(), v2.cend() );
    }
 };

template <typename T1, typename T2>
struct cmvH<std::vector<std::vector<T1>>, std::vector<std::vector<T2>>>
 {
   static void func (std::vector<std::vector<T1>>       & v1,
                     std::vector<std::vector<T2>> const & v2)
    {
      v1.resize( v2.size() );

      std::size_t i { 0U };

      for ( auto const & e2 : v2 )
         cmvH0<std::vector<T1>, std::vector<T2>>::func(v1[i++], e2);
    }
 };

Is there a better way, or an accepted idiom, to do this?

There is no getting away from assigning one element of the array at a time. The best you can do is create a function to help with it.

For example, you could use:

template <typename T1, typename T2>
void vector_copy(std::vector<std::vector<T1>>& dest,
                 std::vector<std::vector<T2>> const& src)
{
   // Add the code to do the copy
}

and then, use

vector_copy(d, i);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM