2D struct array member variable with varying sizes - c++

So I've got a class that I'm generalizing into a base class. One of the member variables is a 2D array of a struct.
struct SomeType
{
...
}
and then in the class's header:
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
But, in my situation, SIZE_TWO needs to be set when the class is initialized because it's going to be different depending on what's using this. What's the best way to have a 2D struct array with a size that's not yet set as a member variable?

The simplest way to solve it is to not use C-style arrays at all, but to use std::vector. Or possibly an std::array of vectors:
std::array<std::vector<SomeType>, SIZE_ONE> member_variable_;
Now you can easily insert as many (or as few) SomeType objects as needed, and still use the array-indexing syntax:
member_variable_[some_index][some_other_index]
To set a fixed size at runtime for the "second" Dimension, you can do something like this in the constructor:
for (auto& v : member_variable_)
v = std::vector<SomeType>(the_runtime_size);

You could use a template:
template<unsigned SIZE_TWO>
class theClass
{
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
SIZE_TWO will be set when you instantiate the class.
theClass<5> tc; //member_variable_ [SIZE_ONE][5];
You could also use containers like std::vector or std::array.

Related

Declaring array of objects without specified size as class field

The field has to be immutable so I can't use the vector. Is there a way to do it like in the title?
I want to do something like this:
typedef list<pair<int,string>> list_pair;
class tree{
private:
list_pair arr[]{
public:
tree(int size){
arr[size];
}
}
Is there a way to do it like in the title?
No.
A non-static member array must have a known size, there is no way around that in C++.
The field has to be immutable so I can't use the vector.
Your example array of non-const isn't immutable either.
Furthermore, I don't see a reason why that should matter. It's a private member, so it's fairly easy to choose to not mutate it. That way the class remains effectively immutable from the outside. Conclusion: Use std::vector.

Anonymous union/structure holding a generic vector

I'm trying to create an anonymous union that holds a generic vector in order to use it as a member in a class without naming the type_name of the union itself.
So that I could call the vector inside the class as following:
vec.size();
But my approach
template <typename T>
union{
std::vector<T> vec;
};
will only give me the error "template class without a name". This also happens with structures. So does it not like to be anonymous when it is generic?
Search results just gave me the option to create a generic vector inside a named structure but, besides I couldn't get this to work either, I would loose the benefits of the anonymous union und I would need to call the vector e.g. as
struct_name.vec.size();
or even
class_name.struct_name.vec.size();
which I tried to avoid.
I want to make the vector generic so that it can store integers or doubles and I don't need to declare two different vectors with their own specific data types. Beside learning some principles of generics I also aim for lesser declarations and storage usage with this technique.
You cannot reliably do what you want. You need at least some way to discriminate at runtime if you have a vector of int or a vector of float.
With C++11 you might code
class StrangeVector {
bool has_int;
union {
std::vector<int> vint;
std::vector<float> vfloat;
};
public:
StrangeVector(bool withints) : has_int(withints) {
if (withints) new(&vint) std::vector<int>();
else new(&vfloat) std::vector<float>();
}
~StrangeVector() {
if (has_int) vint.~vector<int>();
else vfloat.~vector<float>();
}
};
But such code is really bad smelling. (I would suggest using a union of pointers, perhaps of smart pointers e.g. std::shared_ptr or std::unique_ptr, or perhaps std::optional; see this).
See also this, or boost::any ...
Notice that except for RTTI typing information is used at compile time in C++.

c++11 Creating data member for variable-size std::array in class definition

I'm getting a little confused about std::array and passing it around to different classes. I would like to define a class that accepts a std::array in its constructor, and uses that to set a member variable. However, since the arrays could be of variable size, I'm not sure how that translates into the class and member variable declarations. For example:
// array_param.h
#include <array>
class ArrayParam
{
public:
//constructor?
ArrayParam(std::array<long, ?>& entries);
// member variable?
std::array<long, ?> param_entries;
};
...and...
// array_param.cpp
#include "array_param.h"
ArrayParam::ArrayParam(std::array<long, ?>& entries)
{
param_entries = entries;
}
The motivation for this is that in my main program I have, for example, two or more very well defined arrays with known fixed sizes. I would like to perform the same operations on these differently sized arrays, and so such a class to handle these shared operations for arrays of any size is desirable.
Any help is greatly appreciated, thank you very much!
The size of an std::array must be known at compile time. Since you mention your arrays are of known, fixed sizes, you could make the array size a template parameter.
// array_param.h
#include <array>
#include <cstdlib>
template<std::size_t N>
class ArrayParam
{
public:
//constructor?
ArrayParam(std::array<long, N>& entries);
// member variable?
std::array<long, N> param_entries;
};
The length of std::array is required to be known at compile time.
If not, consider using std::vector instead.
From http://www.cplusplus.com/reference/array/array/
an array does not keep any data other than the elements it contains
(not even its size, which is a template parameter, fixed on compile
time).
Based on that, the ArrayParam class may not have much use. I would consider typedef'ing specific kind of arrays, for example
enum { ArrayLength = 1024 };
typedef std::array< long, ArrayLength > LongArray;
// use and test
LongArray myArray;
assert( myArray.size() == ArrayLength );

How do i create a stack of multidimentional arrays

i know how to create a stack of vectors or int ,etc. But i dont know how to create a stack of a multidimentional arrays t[n][n] . Whats the way to implement it?
this is my actual implementation which its not working.
char map[20][20];
stack<map> soluciones;
Edit:
I think due my english most of you didnt undestand my question. Imagine i got some kind of a Game map. I am saving each multidimentional array on the stack. Thats my objective saving the map on a stack
Edit 2: im using Visual Studio 2010 Windows form application
In your code example, you use map (the name of your variable) in place of where a type name must stand (in stack<map> template instantiation). However, it won't work, not even if you use the proper type name (in this case you'd have to use typedef, e.g. typedef char TwoDimCharArray[20][20] and then try std::stack<TwoDimCharArray>:
There is still the problem that arrays don't have a default constructor (which std::stack expects); therefore, std::stack cannot be made to directly contain arrays; you'd have to wrap the array inside a class or struct (which can have a default constructor), e.g.:
class TwoDimCharArray
{
public:
// omit if there's nothing to initialize in map, then the
// compiler-generated constructor will be used
TwoDimCharArray()
{
// ... initalize map values
}
// ... provide access methods to map
private:
char map[20][20];
};
std::stack<TwoDimCharArray> soluciones;
Or use Boost.Array or C++11 std::array stuff! If these are available, they are definitely the better and easier choice!
I guess you should define a proper class for the game map. Then the stack of game maps is not a problem.
class GameMap {
public:
...
private:
char map_[1000][1000];
};
Then it wont matter for the stack how you allocate and manage the map data. E.g.
typedef std::stack<GameMap> GameMapStack;
Ddefine a wrapper class for multidimentional arrays like this:
template <class T, int X, int Y>
class Wrapper
{
public:
T array[X][Y];
}
Then use stack<Wrapper<char, 20, 20> >
First create structure and then define an empty multidimensional char array. then close structure and after thar write push and pop operations.

Declare and initialise an array of struct/class at the same time

1.
I know that it is possible to initialise an array of structures in the declaration. For example:
struct BusStruct
{
string registration_number;
string route;
};
struct BusStruct BusDepot[] =
{
{ "ED3280", "70" },
{ "ED3536", "73" },
{ "FP6583", "74A" },
};
If the structure is changed into a class, like this:
class BusClass
{
protected:
string m_registration_number;
string m_route;
public:
// maybe some public functions to help initialisation
};
Is it possible to do the same as for the structure (i.e. declare and initialise an array of classes at the same time)?
2.
Am I correct to think that it is not possible to declare and initialise vector<BusStruct> or vector<BusClass> at the same time?
Is it possible to do the same as for the structure (i.e. declare and initialise an array of classes at the same time)?
Not unless you create a suitable constructor:
class BusClass
{
protected:
string m_registration_number;
string m_route;
public:
// maybe some public functions to help initialisation
// Indeed:
BusClass(string const& registration_number,
string const& route)
:m_registration_number(registration_number),
m_route(route) { }
};
Or you make all members public and omit the constructor, in which case you can use the same initialization syntax as for the struct. But i think that's not what you intended.
Am I correct to think that it is not possible to declare and initialise vector<BusStruct> or vector<BusClass> at the same time?
No it's not possible with current C++. You can however use libraries that make this possible. I recommend Boost.Assign for that. For that, however, your class has to have a constructor, and likewise your struct too - Or you need to create some kind of factory function
BusStruct make_bus(string const& registration_number,
string const& route) { ... }
If you want to keep the struct initializable with the brace enclosed initializer list in other cases.
No, you would not be able to initialize classes the way you can with structures. But you can write the class constructor inside the array declaration.
C++ has no built in way of initializing vectors, unless you want to load the vector from an array that you have initialized.
C++ natively supports two forms of vector initialization and neither is what you are looking for.
1: Every element the same as in:
vector<int> ints(4,1000); //creates a vector of 4 ints, each value is 1000.
2: Copy from an existing vector as in:
vector<int> original(3,1000); //original vector has 3 values, all equal 1000.
vector<int> otherVector(original.begin(),original.end()); //otherVector has 3 values, copied from original vector