How to create a true array from a vector - c++

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)?

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;

Related

Create a heap-based 2D array without using double pointer syntax?

I need to declare a 2D array as the member variable of a class. I can't use STL (so, no vector), and I've been asked to avoid double/triple pointers. I want to be able to reference elements in this 2D array using subscripting notation, e.g. arr[0][0]. The array also must be declared on the heap due to its size.
Due to the requirements I have, none of the existing answers on StackOverflow meet my needs.
What I've been trying to do is:
class MyClass {
public:
MyClass() : arr(new int[1000][2]) {}
// other stuff here
private:
int arr[1000][2];
};
The error I get after compiling that class is "cannot initialize a parameter of type int * with an lvalue of type int[1000][2]". Clearly, I can solve this by using pointer syntax, but, as mentioned above, I've been asked to use "array syntax" for code clarity. I was hoping someone with a better understanding of C++ could explain how to use "array syntax".
Of course you can do this without double/triple pointers. You can even do this without use of any pointers in the class declaration. But first lets look at the more common approach. A 2D array is a simple extension of a 1D array.
Starting off with the standard way this is done for a 1D array of 1000 ints w/o using vector. The pointer, arr, is on the stack but points to an array of 1000 ints on the heap.
class MyClass {
public:
MyClass() : arr(new int[1000]) {}
private:
int *arr;
};
Elements are accessed the usual way. For instance arr[0]=42;
Extending this to a 2D array in the heap is a simple extension of the above.
You need to declare the member variable as a pointer to a 1D array instead of the basic type.
class MyClass {
public:
MyClass() : arr(new int[1000][2]) {}
private:
int (*arr)[2];
};
Similarly, you can refer to elements of the 2D array the usual way: arr[0][0]=42;
Finally, there is the approach that completely eliminates pointers except the one required for the new. Here we initialize a reference. The trick is to add a third level to new, the [1] so that the *new returns an object that is the actual 2D int array. Structurally, it is no different than what the pointer version above does but lets us directly initialize a reference to a 2D int array. It's certainly not a common idiom so I'd stick with the ptr approach.
class MyClass {
public:
MyClass() : arr(*new int[1][1000][2]) {}
~MyClass() {delete[] arr;}
//private: // to test
int(&arr)[1000][2];
};
int main()
{
MyClass obj;
obj.arr[2][1] = 42;
}
When your class has an array in it, and you use new to create a new instance of that class, that array is on the heap. You can still access the array with arr[i][j].
Why not do something like this?
class myClass {
public:
int arr[1000][2];
};
int main() {
myClass* test = new myClass;
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 2; j++) {
test->arr[i][j] = 5;
}
}
}
You can use 2 classes to achieve this.
class BaseArray {
public:
int& operator[](int x) { return this->arr[x]; }
int operator[](int index) const { return this->arr[index]; }
int arr[2];
};
class myClass {
public:
myClass() {}
~myClass() {}
BaseArray& operator[](int index) { return this->arr[index]; }
BaseArray operator[](int index) const { return this->arr[index]; }
BaseArray arr[1000];
};
Optionally use can use templates to make this class more dynamic.
template<class TYPE, int arraySize>
class BaseArray {
public:
TYPE& operator[](int x) { return this->arr[x]; }
TYPE operator[](int index) const { return this->arr[index]; }
TYPE arr[arraySize];
};
template<class TYPE, int dim1, int dim2>
class myClass {
public:
myClass() {}
~myClass() {}
BaseArray<TYPE, dim2>& operator[](int index) { return this->arr[index]; }
BaseArray<TYPE, dim2> operator[](int index) const { return this->arr[index]; }
BaseArray<TYPE, dim2> arr[dim1];
};
int main()
{
myClass<int, 1000, 2> myArray;
}
EDIT
When you provide the array dimentions int arr[1000][2]; the variable will automatically be allocated in the stack. If the array needs to be fully dynamic, you can just use a double pointer int** arr = { nullptr }; and initialize it at the constructor as shown below.
class myClass {
public:
myClass()
{
arr = new int* [1000];
for (int i = 0; i < 1000; ++i)
arr[i] = new int[2];
}
~myClass()
{
/* Make sure to delete or else it might flag a memory error. */
for (int i = 0; i < 1000; ++i)
delete[] arr[i];
delete[] arr;
}
int** arr = { nullptr };
};

Multidimensional array: operator overloading

I have a class with a multidimensional array:
it is possible to create a one, two, ..., n dimensional array with this class
if the array has n dimensions, i want to use n operator[] to get an object:
example:
A a({2,2,2,2}];
a[0][1][1][0] = 5;
but array is not a vector of pointer which lead to other vectors etc...
so i want the operator[] to return a class object until the last dimension, then return a integer
This is a strongly simplified code, but it shows my problem:
The error i receive: "[Error] cannot convert 'A::B' to 'int' in initialization"
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
#include <iostream> // cin, cout...
class A {
private:
static int* a;
public:
static int dimensions;
A(int i=0) {
dimensions = i;
a = new int[5];
for(int j=0; j<5; j++) a[j]=j;
};
class B{
public:
B operator[](std::ptrdiff_t);
};
class C: public B{
public:
int& operator[](std::ptrdiff_t);
};
B operator[](std::ptrdiff_t);
};
//int A::count = 0;
A::B A::operator[] (std::ptrdiff_t i) {
B res;
if (dimensions <= 1){
res = C();
}
else{
res = B();
}
dimensions--;
return res;
}
A::B A::B::operator[] (std::ptrdiff_t i){
B res;
if (dimensions <=1){
res = B();
}
else{
res = C();
}
dimensions--;
return res;
}
int& A::C::operator[](std::ptrdiff_t i){
return *(a+i);
}
int main(){
A* obj = new A(5);
int res = obj[1][1][1][1][1];
std::cout<< res << std::endl;
}
The operator[] is evaluated from left to right in obj[1][1]...[1], so obj[1] returns a B object. Suppose now you just have int res = obj[1], then you'll assign to a B object (or C object in the case of multiple invocations of []) an int, but there is no conversion from B or C to int. You probably need to write a conversion operator, like
operator int()
{
// convert to int here
}
for A, B and C, as overloaded operators are not inherited.
I got rid of your compiling error just by writing such operators for A and B (of course I have linking errors since there are un-defined functions).
Also, note that if you want to write something like obj[1][1]...[1] = 10, you need to overload operator=, as again there is no implicit conversion from int to A or your proxy objects.
Hope this makes sense.
PS: see also #Oncaphillis' comment!
vsoftco is totally right, you need to implement an overload operator if you want to actually access your elements. This is necessary if you want it to be dynamic, which is how you describe it. I actually thought this was an interesting problem, so I implemented what you described as a template. I think it works, but a few things might be slightly off. Here's the code:
template<typename T>
class nDimArray {
using thisT = nDimArray<T>;
T m_value;
std::vector<thisT*> m_children;
public:
nDimArray(std::vector<T> sizes) {
assert(sizes.size() != 0);
int thisSize = sizes[sizes.size() - 1];
sizes.pop_back();
m_children.resize(thisSize);
if(sizes.size() == 0) {
//initialize elements
for(auto &c : m_children) {
c = new nDimArray(T(0));
}
} else {
//initialize children
for(auto &c : m_children) {
c = new nDimArray(sizes);
}
}
}
~nDimArray() {
for(auto &c : m_children) {
delete c;
}
}
nDimArray<T> &operator[](const unsigned int index) {
assert(!isElement());
assert(index < m_children.size());
return *m_children[index];
}
//icky dynamic cast operators
operator T() {
assert(isElement());
return m_value;
}
T &operator=(T value) {
assert(isElement());
m_value = value;
return m_value;
}
private:
nDimArray(T value) {
m_value = value;
}
bool isElement() const {
return m_children.size() == 0;
}
//no implementation yet
nDimArray(const nDimArray&);
nDimArray&operator=(const nDimArray&);
};
The basic idea is that this class can either act as an array of arrays, or an element. That means that in fact an array of arrays COULD be an array of elements! When you want to get a value, it tries to cast it to an element, and if that doesn't work, it just throws an assertion error.
Hopefully it makes sense, and of course if you have any questions ask away! In fact, I hope you do ask because the scope of the problem you describe is greater than you probably think it is.
It could be fun to use a Russian-doll style template class for this.
// general template where 'd' indicates the number of dimensions of the container
// and 'n' indicates the length of each dimension
// with a bit more template magic, we could probably support each
// dimension being able to have it's own size
template<size_t d, size_t n>
class foo
{
private:
foo<d-1, n> data[n];
public:
foo<d-1, n>& operator[](std::ptrdiff_t x)
{
return data[x];
}
};
// a specialization for one dimension. n can still specify the length
template<size_t n>
class foo<1, n>
{
private:
int data[n];
public:
int& operator[](std::ptrdiff_t x)
{
return data[x];
}
};
int main(int argc, char** argv)
{
foo<3, 10> myFoo;
for(int i=0; i<10; ++i)
for(int j=0; j<10; ++j)
for(int k=0; k<10; ++k)
myFoo[i][j][k] = i*10000 + j*100 + k;
return myFoo[9][9][9]; // would be 090909 in this case
}
Each dimension keeps an array of previous-dimension elements. Dimension 1 uses the base specialization that tracks a 1D int array. Dimension 2 would then keep an array of one-dimentional arrays, D3 would have an array of two-dimensional arrays, etc. Then access looks the same as native multi-dimensional arrays. I'm using arrays inside the class in my example. This makes all the memory contiguous for the n-dimensional arrays, and doesn't require dynamic allocations inside the class. However, you could provide the same functionality with dynamic allocation as well.

C++ how call template's class constructor

I have such piece of code:
template <class T>
struct Rgb
{
T *r, *g, *b;
Rgb(int nr, int ng, int nb)
{
r = new T(nr);
g = new T(ng);
b = new T(nb);
}
Rgb(int n)
{
Rgb(n, n, n);
}
~Rgb()
{
delete r;
delete g;
delete b;
}
};
I have done it in such way, because I want to be able to create objects like:
Rgb<std::vector<int>> a(10); // so it creates 3 vectors inside,
// each with 10 elements or
Rgb<std::deque<double>> a(2, 5, 4); // so it creates 3 deques inside
// with different sizes
But the implementation I have given above does not work. Help me please... thanks...
If you compiler supports constructor delegation (which e.g. Clang 3.2 does) you can do the following:
Rgb(int n) : Rgb(n, n, n)
{
}
What you're doing is constructing a temporary Rgb instance in the constructor, which will fail once the uninitialized r, g and b get deleted.
Otherwise I'd recommend either creating a common init function that does the initialization or simply duplicate the code. And as the comments are noting you shouldn't use new here (that's almost always a code smell in modern C++ code). Bringing this together:
template <class T>
struct Rgb
{
T r, g, b;
Rgb(int nr, int ng, int nb) : r(nr), g(ng), b(nb)
{ }
Rgb(int n) : r(n), g(n), b(n)
{ }
~Rgb()
{ }
};

Multi-dimensional array

I need to create a function that has a parameter which is a multi-dimensional array with two dimensions being user-specified, e.g.
int function(int a, int b, int array[a][b])
{
...
}
How would I do that in C++ ?
Are the dimensions known at compile-time? In that case, turn them into template parameters and pass the array by reference:
template<int a, int b>
int function(int(&array)[a][b])
{
...
}
Example client code:
int x[3][7];
function(x);
int y[6][2];
function(y);
Assuming the dimensions are not known at compile time, you emulate a two dimensional array with a one dimensional array:
int& getat(int x, int y, int r, int c, int *array) {return array[y*c+x];}
int function(int a, int b, int *array) {
getat(4, 2, a, b, array) = 32; //array[4,2] = 32
}
or, for safety, wrap it all in a class:
template <class T>
class array2d {
std::vector<T> data;
unsigned cols, rows;
public:
array2d() : data(), cols(0), rows(0) {}
array2d(unsigned c, unsigned r) : data(c*r), cols(c), rows(r) {}
T& operator()(unsigned c, unsigned r) {
assert(c<cols&&r<rows);
return data[r*cols+c];
}
};
or, best yet, use Boost's Multidimensional Array, which will be better than anything mere mortals could write.
I'm not sure if this work, because your question and code are not the same, according to your code the function can have 3 parameters, so this would work:
int function(int a, int b, int** &array)
{
array = new int*[a];
for (int i =0;i<a;i++)
array[i] = new int[b];
// I don't know why you are returning int, probably doing something here....
}
However your question says that your function can take only one parameter, so:
if the dimensions are known at compile time, then Fred's Answer is the best (it charmed me in fact! :) ).
if not, I can't see any possible solution that allows passing more than one user-specified value other than encapsulating all these values in one object.
Like this:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
int a,b;
int** array;
};
int function(Foo &f)
{
f.array = new int*[f.a];
for (int i = 0;i<f.a;i++)
f.array[i] = new int[f.b];
// I don't know why you are returning int, probably doing something here....
}
Though I find it a bad idea, in fact the function could be a parameterless method instead:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
void Create() // Or could do this right in the Constructor
{
array = new int*[a];
for (int i = 0;i<a;i++)
array[i] = new int[b];
}
private:
int a,b;
int** array;
};
Still this is a bad idea, because you are reinventing the wheel, as there are a perfect class in the STL to do all the work for you:
vector< vector<int> > v; // Now v is a 2D array

Create an array of an array of structs?

this question is regarding the syntax of an array of array of structs.
I have a struct that takes in two ints:
struct point
{
int x, y;
};
I have created another struct that takes in 8 of these structs:
//Creating an Array of Array of structs
struct Arraypoint
{
point variable[8];
};
//Not sure if this is the correct way to do it.
Now, in main, I want to declare an array variable of type Arraypoint with 8 indices, so effectively I will have 8 * 8 = 64 elements of struct point and 128 ints (64 x and 64 y).
Also, how would I access an individual element struct point from the array Arraypoint?
Okay after having declared in main lets say Arraypoint is 2.
Arraypoint arr[2];
How do I initialize the elements without having to type in arr[0].variable[0].x = ... or without using for loops.
Why can't I do the following, it doesn't seem to work.
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }//xy are rand
I have used curly braces in my code, the error returned is missing braces around initializer for type point and too many initializers for type Arraypoint.
In C++, you'd just write:
Arraypoint arr[8];
An individual point could then be accessed via:
arr[i].variable[j];
More practically, though, you'd probably be better off using e.g.
std::vector<std::vector<point> >
or writing your own class with an overloaded operator(int i, int j). For example:
class PointMatrix
{
private:
std::vector<point> m_points;
public:
PointMatrix() : m_points(64) {}
point& operator()(int i, int j) { return m_points[8 * i + j]; }
const point& operator()(int i, int j) const { return m_points[8 * i + j]; }
};
PointMatrix mat;
m(3, 4).x = 23;
got it: ideone.com/ix3hC. Arraypoint::variable has to have it's own { } pair.
struct point
{
int x, y;
};
#define P {0, 0}
struct Arraypoint
{
point variable[8];
};
#define V { P, P, P, P, P, P, P, P}
#define AP { V } //this is the pair you missed
int main() {
Arraypoint arr[2] = { AP, AP };
}
struct Arraypoint arraypoints[8];
is what you're after, I think. To use them:
int firstx = arraypoints[0].variable[0].x;
This isn't so pretty though
struct point { int x, y; };
struct point[8][8] arraypoints;
Is probably better? Don't know what exactly you're after though.
To create an array of Arraypoints, you can do:
Arraypoint arr[8];
To access an element:
arr[i]
will return the i'th Arraypoint element
arr[i].variable[j]
will return the j'th point in the element
arr[i].variable[j].x
will return the x coordinate of that point.
So I realized why I couldn't declare my array as such,
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }
//xy are randomn integer values
its because in my struct declaration of Arraypoint, it takes in 8 elements of type point. So
I have to create variables of type point to store(x,y) and then i could store this variable in Array point.
point point1 = {x,y}, ...;
Arraypoint arr[2] = { {point1,point2,point3,point4,point5,....} };
Just for anyone in the future who stumbles across the same problem.