简体   繁体   English

将 c 多维数组转换为多维 c++ 向量

[英]convert c multidimensional array to multidimensional c++ vector

i am trying to convert c multidimensional array to multidimensional c++ vector, i mean, to convert something like this int arr[2][3] = {{1,2,3}, {4,5,6}};我正在尝试将 c 多维数组转换为多维 c++ 向量,我的意思是,转换像这样的int arr[2][3] = {{1,2,3}, {4,5,6}}; into the correspondent vector.进入对应的向量。
The array isn't necessarily 2D shaped, it could also be something like this:数组不一定是 2D 形状的,它也可能是这样的:

int arr[2][2][3] = {
   {
      {1,2,3},
      {4,5,6},
   },
   {
      {7,8,9},
      {10,11,12},
   }
};

initially i thought that something like this would have worked, but it didn't really turned out to be the case because it seems like if std::vector doesn't allows conversions from C arrays.最初我认为这样的事情会起作用,但事实并非如此,因为似乎std::vector不允许从 C arrays 进行转换。

std::vector<std::any> V(arr);

Then i thought at something like function recursion, this is my attempt, that (i don't know why!) throws error: no matching function for call to 'length' .然后我想到了 function 递归之类的东西,这是我的尝试,(我不知道为什么!)抛出error: no matching function for call to 'length'

#include <iostream>
#include <type_traits>
#include <vector>
#include <any>

// Get the lenght of a classic C array.
template <class T, unsigned S>
inline unsigned length(const T (&v)[S]) {
  return S;
};

// Check wether the input is a classic C array or not.
template <class T>
bool is(const T& t) {
  return std::is_array_v<T>;
};

// Turn the classic C input array to vector.
template <class T>
std::vector<std::any> toVector(const T& t) {
  std::vector<std::any> V;
  for (int k = 0; k < length(t); k++) {
    if (is(t[k])) {
      V.push_back(toVector(t[k]));
    } else {
      V.push_back(t[k]);
    }
  }
  return V;
}

int main() {

  int16 a[] = {1,2,3};

  auto b = toVector(a);

}

What did i wrong in the second attempt?我在第二次尝试中做错了什么? Alternatively, is there a simpler way to manage to do this?或者,有没有更简单的方法来做到这一点?
Also, i think it would be better to convert all the numbers in the vector to a unique given data type, is this possible?另外,我认为将向量中的所有数字转换为唯一的给定数据类型会更好,这可能吗?
I am using c++11 and g++ as compiler –我使用 c++11 和 g++ 作为编译器 –

Note that i do not know how many dimensions my array has.请注意,我不知道我的数组有多少维。

The equivalent of a C multidimensional array is a flat C++ vector plus a mumtidimensional array view. C 多维数组的等价物是平面 C++ 向量加上多维数组视图。

The naive equivalent is a vector of vectors (maybe of vectors), which actually corresponds to a C "jagged" array.朴素的等价物是向量的向量(可能是向量),它实际上对应于 C “锯齿状”数组。 The memory layout and performance characteristics will be very different. memory 布局和性能特点会有很大不同。

There are many multi dimensional array-view implementstions on the web. web 上有许多多维数组视图实现。

template<class A>
struct raw_ptr { using type=A*; };
template<class A, std::size_t N>
struct raw_ptr<A[N]>:raw_ptr<A>{};

template<class A>
using raw_ptr_t = typename raw_ptr<A>::type;

template<class T>
struct array_view;

template<class T, std::size_t D0, std::size_t D1>
struct array_view<T[D0][D1]> {
  T(*data)[D1]=0;
  constexpr array_view( T(&arr)[D0][D1] ):data(arr) {}
  explicit array_view( raw_ptr_t<T> buff ):data(reinterpret_cast<T(*)[D1]>(buff)) {}
  constexpr array_view<T[D1]> operator[](std::size_t i)const{
    return data[i];
  }
};
template<class T, std::size_t D0>
struct array_view<T[D0]> {
  constexpr array_view( T(&arr)[D0] ):data(arr) {}
  explicit constexpr array_view( T* buff ):data(buff) {}

  T* data=0;
  constexpr T& operator[](std::size_t i)const{
    return data[i];
  }
};

to convert a int[4][5][6] you'd do:转换一个int[4][5][6]你会做:

int array[4][5][6]={/*whatever*/};
std::vector<int> buff(&array[0][0][0], &array[3][4][5]);
array_view<int[4][5][6]> view{buff.data()};

now, view[a][b][c] is the same as array[a][b][c] .现在, view[a][b][c]array[a][b][c]相同。

Live example .活生生的例子

template<class Array>
struct wrap_array_in_vector {
  using raw_ptr = raw_ptr_t<Array>;
  using value_type = std::remove_pointer_t<raw_ptr>;
  std::vector<value_type> data;
  array_view<Array> view;
  wrap_array_in_vector(wrap_array_in_vector const& other):
    data(other.data),
    view(data.data())
  {}
  wrap_array_in_vector(wrap_array_in_vector && other):
    data(std::move(other.data)),
    view(data.data())
  {
    other.view.data = nullptr; // no longer valid
  }
  decltype(auto) operator[](std::size_t i)const {
    return view[i];
  }
  wrap_array_in_vector( Array const& arr ):
    data( reinterpret_cast<value_type const*>(&arr[0]), reinterpret_cast<value_type const*>(&arr[1]) ),
    view(data.data())
  {}
};
template<class Array>
wrap_array_in_vector(Array&)->wrap_array_in_vector<Array>;
template<class Array>
wrap_array_in_vector(Array const&)->wrap_array_in_vector<Array>;

this lets you do这让你做

wrap_array_in_vector wrapped = array;

and wrapped deduces all of its type information it needs.并且wrapped推断出它需要的所有类型信息。

This should be close to optimal for conversion to a vector.这应该接近于转换为向量的最佳值。 The part of the description that was misleading was that the sizes are not regular, as they are list-initialized and in this case with int, will be zeros.描述中误导的部分是大小不规则,因为它们是列表初始化的,在这种情况下使用 int,将为零。

#include <type_traits>
#include <vector>
#include <iostream>

template<typename T, std::size_t N>
auto to_vectors( T const (&c_array)[N] ) {
    using element_base_type = std::decay_t<T>;
    if constexpr( std::is_array_v<T> ) {
        using child_t = std::remove_cv_t<std::remove_reference_t<decltype( to_vectors( c_array[0] ) )>>;
        auto result = std::vector<child_t>( );
        result.reserve( N );
        for( auto const & element: c_array ) {
            result.push_back( to_vectors( element ) );
        }
        return result;
    } else {
        return std::vector<T>( c_array, c_array + N );
    }
 }


 int arr[2][2][3] = {
   {
      {1,2,3},
      {4,5,6},
   },
   {
      {7,8,9},
   }
};

auto v0 = to_vectors( arr );


template<typename Vec>
void display( Vec const & vec ) {
    if constexpr( std::is_same_v<int, typename Vec::value_type> ) {
        std::cout << "elements: {";
        for( int e: vec ) {
            std::cout << e << ',';
        }
        std::cout << "}\n";
    } else {
        std::cout << "element count: " << vec.size( ) << '\n';
        for( auto const & child: vec ) {
            display( child );
        }
    }
}


int main( ) {
    display( v0 );
}

this will output这将 output

element count: 2
element count: 2
elements: {1,2,3,}
elements: {4,5,6,}
element count: 2
elements: {7,8,9,}
elements: {0,0,0,}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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