0

I have a vector (of strings) that I need to pass into a function that only accepts a true array(not a pointer).

//Function only accepts arrays, not vectors or pointers
//It has to be an array so that the compiler can figure out N
template<typename T, typename U, size_t N>
T* createElementFromArray(U (&a)[N]){
    return createElementFromArrayHelper<T>(std::make_index_sequence<N>{}, a);
}

The problem is, I need to dynamically allocate the array so that it is the same size as the vector, but new[] only returns a pointer not a true array.

How do I dynamically allocate a true array, not a pointer? Or is there another way to create a vector from an array(the array needs to be the exact same size as the vector)?

  • Just to make sure that was not forgetting something I just tried this: `void foo() { new char[10]; }`. And it worked. I allocated a "true array". Can you provide more details as to what your problem is? – Sam Varshavchik Feb 18 '22 at 00:25
  • 1
    The function depends on the size of the array at compile-time. You cannot use it with a vector/array with runtime-determined size. – user17732522 Feb 18 '22 at 00:26
  • 1
    Sounds like you need to cast a pointer to an array to a reference to an array. Does this answer your question? [Is it legal to cast a pointer to array reference using static_cast in C++?](https://stackoverflow.com/questions/21317140/is-it-legal-to-cast-a-pointer-to-array-reference-using-static-cast-in-c) – François Andrieux Feb 18 '22 at 00:26
  • 1
    You can't use that function. `N` in this context is compile-time; not run-time. There is no way to manufacture a compile-time construct (a native array of magnitude `N`) from a run-time determination (a vector of magnitude `.size()`). An overload is likely your only option. – WhozCraig Feb 18 '22 at 00:26
  • @WhozCraig How would an overload help with this? – Gary Fisher Feb 18 '22 at 00:43
  • 2
    @GaryFisher it would help if an overload exists that takes runtime parameters accepting a pointer to an array of values and the number of values in that array, eg: `template T* createElementFromArray(U* a, size_t N)` Then you can pass in a `std::vector`, a `std::array`, memory from `new[]`, etc. The real question is, what does `createElementFromArray()` actually do, and why can it do that only at compile-time, not at runtime? What does `createElementFromArrayHelper` look like? – Remy Lebeau Feb 18 '22 at 01:26
  • If the function you mention only works with an array object and doesn't work with a pointer than necessarily it must require an array of a specific size, otherwise it couldn't accept an array (which must be passed by reference). This fixed size should simplify the problem. – François Andrieux Feb 18 '22 at 02:01
  • 1
    If you mean that you want to pass data from a `std::vector` as an argument for your `createElementFromArray()` function, then it's not possible (unless you write distinct code for every possible size of the vector, which sort of defeats the point of using a `std::vector`). The size (number of elements) of a `vector` is determined at run time, and the size of the array expected by your templated `createElementFromArray()` function must be known at compile time. – Peter Feb 18 '22 at 02:01
  • @RemyLebeau `createElementFromArray` is from [this](https://stackoverflow.com/a/71097534/17845427) answer, but I need it to work with a vector not an array so that it can be any size. Is there any way this is possible? – Gary Fisher Feb 18 '22 at 02:49
  • @GaryFisher see the answer I just posted. – Remy Lebeau Feb 18 '22 at 04:22
  • This feels like an XY problem coupled with https://stackoverflow.com/questions/71097511/pass-a-variable-number-of-arguments-into-a-function – tevemadar Feb 27 '22 at 16:26

1 Answers1

1

Based on the code in this answer, where you got CreateElementFromArray() from, what you are asking for is simply not possible at all.

CreateElementFromArray() converts a fixed-sized array of N values into a sequence of N parameters passed to T's constructor at compile-time. For example, this code from that same answer:

struct A {
    A(int a, int b) : x(a), y(b) {}
    int x, y;
};

int Aargs[] = { 1, 2 };
A* a = createElementFromArray<A>(Aargs);
delete a; 

Is translated by the compiler into this code:

struct A {
    A(int a, int b) : x(a), y(b) {}
    int x, y;
};

int Aargs[] = { 1, 2 };
A* a = new A(Aargs[0], Aargs[1]);
delete a; 

That kind of translation is simply not possible with a std::vector or other dynamic array allocated at runtime.

However, if T's constructor accepts a vector/array as input, you can use createElement() from that same answer instead:

template<typename T, typename... TArgs>
T* createElement(TArgs&&... MArgs)

Whatever you pass to createElement() gets passed as-is to T' s constructor. For example:

struct A {
    A(int* values, size_t N) : values(values, values+N) {}
    A(const vector<int> &values) : values(values) {}
    vector<int> values;
};

vector<int> Aargs1 = { 1, 2 };
array<int, 3> Aargs2 = { 1, 2, 3 };
int* Aargs3 = new int[4]{ 1, 2, 3, 4 };

A* a = createElement<A>(Aargs1);
delete a;

a = createElement<A>(Aargs1.data(), Aargs1.size());
delete a;

a = createElement<A>(Aargs2.data(), Aargs2.size());
delete a;  

a = createElement<A>(Aargs3, 4);
delete a;

delete[] Aargs3;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770