0

My goal is to construct a function that would transform an array into n-dimensional vector given dimensions as variadic arguments.

For example for two dimensions.

template<T>
vector<vector<T>> from_array(T *array, size_t d1, size_t d2) {
    auto v = vector<vector<T>();
    v.reserve(d2);
    for (n = 0; n < d2; n++) {
         vector(array, array + size)
    }
}

I've googled for a while and it seems like I want Homogeneous variadic function parameters, but they aren't available in c++. But maybe there's a simpler solution or a workaround?

Also seems like I would need to use decltype, but my experience with c++ is almost nil, so I'm not sure how to use it.

user1685095
  • 5,787
  • 9
  • 51
  • 100
  • Please provide examples how usage of template should look like (this better defines how it should be implemented then your approach to this implementation). – Marek R Mar 19 '21 at 17:04
  • 1
    There is a more fundamental problem here: C++ does not work this way. You cannot create a different type based on some runtime parameter, unless you explicitly check for each possible value of the parameter and instantiate the corresponding type instance. – Sam Varshavchik Mar 19 '21 at 17:05
  • 2
    Personally I would ditch returning vectors and instead write a class that encapsulates a 1d vector and treats the buffer as whatever dimension you need by provided the correct access functions to it. This gives you the best performance you can and it's a lot easier to figure out and write. – NathanOliver Mar 19 '21 at 17:06
  • @SamVarshavchik this is not that case. I think number of arguments defines return type here and this is know during compile time. – Marek R Mar 19 '21 at 17:09
  • Rough sketch of that idea can be seen here: You can a see a base example here: https://stackoverflow.com/questions/43358369/c-n-nested-vectors-at-runtime/43358434#43358434 – NathanOliver Mar 19 '21 at 17:12
  • If you want homogeneous for `template *..*/> void foo(size_t... sz)`, you might still work around with `template void foo(Ts... sz)`. – Jarod42 Mar 19 '21 at 17:25
  • the paper you link presents some workarounds. You cannot have homogeneous variadic function parameters, but you can write code that achieves the same. – 463035818_is_not_an_ai Mar 19 '21 at 17:37

1 Answers1

5

It's fairly straight-forward if you don't mind reversing the order of the size arguments (so the outer-most dimension is the first argument rather than the last):

template <class T>
auto from_array(const T*array, size_t d0) {
  return std::vector<T>(array, array + d0);
}

template <class T, class... Sizes>
auto from_array(const T *array, size_t d0, Sizes... szs) {
  std::vector<decltype(from_array(array, szs...))> ret;
  ret.reserve(d0);
  for (size_t i = 0; i < d0; ++i) {
      ret.emplace_back(from_array(array, szs...));
      array += (szs * ... * 1);
  }
  return ret;
}

But I agree with the comment that mentions it's probably a better idea to encapsulate your array with an accessor that treats it as multi-dimensional, rather than copying it into a bunch of nested vectors.

Kyle
  • 6,500
  • 2
  • 31
  • 41
  • Thanks I’ll try your solution later. As to incapsulation - It’s obviously better, and I would’ve done so If that was my code, but it’s not. I’m just creating a c wrapper for existing c++ library to create Rust wrapper for it. – user1685095 Mar 19 '21 at 19:30