C++ - Return multidimensional array from function - c++

I am writing a code for Cellular Automata and I need an evolution function to calculate the state of the automata after a time step.
I choose to call this function evol, to test it I created an elementary function in C++. Unfortunately it does not compile since the compiler cannot understand that I need it to return an array. Here is the code :
#include <iostream>
#include <cmath>
#include <vector>
#include <string>
using namespace std;
const int N = 51; // Size of the grid; two columns/rows are added at the beginning and the end of the array (no evolution of the CA on the boundaries)
class Cell{
//defining whats a cell here
};
void showCA(Cell CA[N+2][N+2]){
//function to print the CA grid in the terminal
}
Cell[N+2][N+2] evol(Cell CA[N+2][N+2]){
return CA;
}
int main()
{
// Initialisation
cout << "Initialisation" << endl;
static Cell CA[N+2][N+2];
// some code here to initialize properly the Cell array.
showCA(CA);
CA = evol(CA);
showCA(CA);
return 0;
}
The compiler returns this error :
error: expected unqualified-id
Cell[N+2][N+2] evol(Cell CA[N+2][N+2]){
Any idea on how I should implement this ?

You cannot return arrays from functions:
ยง 8.3.5/8
Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things.
If you are wishing to return raw, C-style arrays from functions, then you have to use a reference or pointer. For example, here's how it is done using a reference (you can do the same using a pointer by replacing & with *):
Cell (&evol(Cell (&CA)[N+2][N+2]))[N+2][N+2];
However, this is very unintuitive and hard to read. If your compiler supports the latest standard (C++11) the return type can be cleaned up using a trailing return type:
auto evol(Cell (&CA)[N+2][N+2]) -> Cell(&)[N+2][N+2];
But again, this is probably still harder to read.
C++11 facilitates the handling of C-style arrays with the container std::array<>. Non-C++11 code should use std::vector<>:
using Cells = std::array<std::array<Cell, N+2>, N+2>;
Cells const& evol(Cells const& CA);

You can use
typedef std::vector<std::vector<Cell>> CellArray;
CellArray Cells(N+2); // resize main dimension
for (size_t i=0; i<N+2; i++)
Cells[i].resize(N+2); // resize all cells of main dimension
to hold your cell array, but you also need to add a copy constructor and operator= in Cell class
class Cell {
public:
Cell() { ... default ctor code here ... }
Cell(const Cell &c) { *this = c; }
Cell &operator=(const Cell&c)
{
if (this != &c)
{
... copy data from c members to this members here ...
}
return *this;
}
};
Your evol function then can return a CellArray:
CellArray evol(CellArray &c)
{
CellArray r;
... do some calculations with c and r ...
return r;
}

once you have declared a variable using the array syntax like you have:
Cell CA[N+2][N+2];
you cannot assign CA to be something else. You can only assign values to its contents. Hence,
CA = evol(CA);
is wrong.
You can do the following:
Cell (*CA2)[N+2] = evol(CA);

As the number of elements seems to be fixed, I suggest you use the std::array container:
const int N = 51;
typedef std::array<std::array<Cell,N+2>, N+2> datatype;
You can then use this type as a return type:
datatype Evol( const datatype& d );
You can access elements just as if it was a "C" array:
datatype d;
Cell c;
d[10][20] = c;

I would strongly suggest encapsulate your array into a class. You cannot return an array, but you can return an object that contains an array.

Related

vector of variable type vectors

I am currently implementing a data storage for a large table in C++. The table needs to be able to store different data type for each of a variable number of columns.
The type and the length of each column are defined and run-time. Because of this, I figured, a vector of pointer to vectors would be the right approach. I can however not figure out how to do this with variable data types.
I looked at How to get a vector of different vectors in C++ but there is not dynamic solution.
I am open to any other solutions, I don't necessarily need vectors, but the table should be re-sizable at run-time.
It should look something like this:
0 1 2 3 ...
- - - - -
1 a 0 1.3 ...
2 b 1 2.5 ...
3 c 0 1.5 ...
4 d 0 0.8 ...
5 e 1 1.2 ...
.. .. .. ... ...
I some people have suggested using boost::any but I am a bit reluctant of this (in terms of efficiency) because the table has to load large packet files from disk.
The any Class implemented in boost will do what you need.
Here is an example how to use it from their website:
#include <vector>
#include <boost/any.hpp>
using boost::any_cast;
typedef std::vector<boost::any> many;
void append_int(many & values, int value)
{
boost::any to_append = value;
values.push_back(to_append);
}
void append_string(many & values, const std::string & value)
{
values.push_back(value);
}
void append_char_ptr(many & values, const char * value)
{
values.push_back(value);
}
void append_any(many & values, const boost::any & value)
{
values.push_back(value);
}
void append_nothing(many & values)
{
values.push_back(boost::any());
}
If you cannot use boost and do not want to re-implement boost::any you could use void * as the poor man's any container. The table level would be a std::vector<void *> and each column (of type T) would be a std::vector<T>. You then allocate each column in turn and store the address of the column in the initial std::vector<void *>.
Provided you cast the value of each column before using it it should work. Depending on your requirements it may be more or less simple to implement that correctly because as you have raw pointers you should implement carefully the destructors and if appropriate copy an move constructors and assignements or declare them deleted. But it is a (poor man's) boost alternative...
To store different types in vector is impossible, but if you store pointers without type (void*), then you can retype it to any type you want. If you don't know at runtime what type you are reading, then make struct containing pointer void* and variable to determine type.
It's while since I used C++ so example can be just pseudo C++.
#include<vector>
#include<iostream>
void workWithCharArray(char* c);
typedef struct mytype {
int type = 0; // this defining default values is available since C++11
void* var = nullptr;
} Mytype;
int main() {
char* ptr = (char*)"Testing string";
std::vector<Mytype> container;
Mytype tostore;
tostore.type = 1;
tostore.var = (void*)ptr;
container.append(tostore);
switch (tostore.type) {
case 1:
workWithCharArray((char*)tostore.var);
break;
default:
std::cerr << "Unknown type - Error handling";
}
return 0;
}
void workWithCharArray(char* c) {
std::cout << c << std::endl;
}
If you need a two-dimensional vector that stores one-dimensional vectors of different data types, you could create an abstract, non-templated base class for the inner vector and then store pointers to that abstract base class in the outer vector, utilising polymorphism if you want to call member functions on the abstract vectors.
class AbstractVector {
... // provide pure virtual interface here
}
template<class T>
class MyVector : public AbstractVector, public std::vector<T> {
... /* provide implementation of pure virtual interface using
already available functionality from std::vector here */
}
In your implementation you can then store pointers to the base class AbstractVector (or unique_ptrs or shared_ptrs depending on what you want to do):
std::vector<AbstractVector *> table;
MyVector<int> * columnOne = new MyVector<int>;
MyVector<float> * columnTwo = new MyVector<float>;
table.push_back(columnOne);
table.push_back(columnTwo);

passing an array into a class function from another class's constructor

Sorry for the confusing title, basically I have created two classes, one is an object, and the other being a box that contains an array of such objects. so what I want to do is create a function/constructor inside the object class that takes in an array of ints and stores them inside the box. I want to be able to call this function through the box class constructor to initialize these objects. So ive tried something like below but it isnt working at all, since only the first value of the array gets passed through. What am I doing wrong?
#include <iostream>
#include <string>
class object{
string objectName;
int values[];
public:
void createObject(int[]);
}
class Box{
object objects[100];
public:
Box();
}
Box::Box (void){
int array1[2];
int array2[15];
object[1].createObject(array1);
object[2].createObject(array2);
}
Object::Object(int Values[]){
values = Values;
}
You should really use std::vector. The problem with arrays is that they decay to pointers when passed as arguments to functions. As a consequence, If you want to store a private copy of the elements you are forced to use heap-allocated objects and consequently do memory management by hand (with all the pain it causes).
It is much better to rely on data members that permit applying the rule of zero.
Here's a tentative solution:
#include <iostream>
#include <string>
#include <vector>
class object {
public:
object(std::vector<int> const& v, std::string const& object_name): v_(v.begin(), v.end()), object_name_(object_name) {}
private:
std::vector<int> v_;
std::string object_name_;
};
class box {
public:
box(std::vector<object> const& objects): objects_(objects) {};
private:
std::vector<object> objects_;
};
I recommend you instead use a std::vector. Arrays don't really work well being passed to functions. When you define Object::Object(int Values[]) you are simply passing the first element of this array by value. If you were to use vectors, the function would look like this:
Object::Object(std::vector<int> &Values):
values(Values)
{
}
The problem with the code is in your thinking on what the array is. In C++, all an array is, is a memory pointer. The language allows you to pass an index into the array pointer to access whatever chunk of data lives at that index.
Whenever you pass arrays between functions or classes, pass the array name only. It will be interpreted as a pointer, and won't copy any data. When you do this, you must also pass the length of the array.
Granted, most people stick with vector<> because it's easier, takes care of memory leaks (mostly) and is VERY efficient. But I like doing it myself. It's good for you. I would try:
#include <iostream>
#include <string>
class Object
{
string _objectName;
int *_values;
int _myLength;
Object();
~Object();
void createObject(int *pValues, int arrLength);
}
class Box
{
_Object objects[100];
Box();
}
Box::Box(void) {
int array1[2];
int array2[15];
object[1].createObject(array1, 2);
object[2].createObject(array2, 15);
}
Object::Object() {
_values = null_ptr;
_myLength = 0;
}
Object::~Object() {
delete[] _values;
}
void Object::createObject(int *pvalues, int arrLength) {
_myLength = arrLength;
_values = new int[_myLength];
for(int ndx=0; ndx<arrLength; ndx++) {
_values[ndx] = pvalues[ndx];
}
}
-CAUTION-
I just adapted your code you provided, and added some conventions. There are a couple places in the code where I'm not sure what the purpose is, but there you go. This should give you a good head start.

Function that returns a pointer to const 2-d array (C++)

I'm an intermittent programmer and seem to have forgotten a lot of basics recently.
I've created a class SimPars to hold several two-dimensional arrays; the one shown below is demPMFs. I'm going to pass a pointer to an instance of SimPars to other classes, and I want these classes to be able to read the arrays using SimPars accessor functions. Speed and memory are important.
I know life is often simpler with vectors, but in this case, I'd really like to stick to arrays.
How do I write the accessor functions for the arrays? If I'm interested in the nth array index, how would I access it using the returned pointer? (Should I write a separate accessor function for a particular index of the array?) What's below is certainly wrong.
// SimPars.h
#ifndef SIMPARS_H
#define SIMPARS_H
#include "Parameters.h" // includes array size information
class SimPars {
public:
SimPars( void );
~SimPars( void );
const double [][ INIT_NUM_AGE_CATS ] get_demPMFs() const;
private:
double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
};
#endif
// SimPars.cpp
SimPars::SimPars() {
demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
// ...code snipped--demPMFs gets initialized...
}
//...destructor snipped
const double [][ INIT_NUM_AGE_CATS ] SimPars::get_demPMFs( void ) const {
return demPMFs;
}
I would greatly appreciate some kind of explanation with proposed solutions.
Basically, you have three options: return the entire array by reference, return the first row by pointer, or return the entire array by pointer. Here is the implementation:
typedef double array_row[INIT_NUM_AGE_CATS];
typedef array_row array_t[NUM_SOCIODEM_FILES];
array_t demPMFs;
const array_t& return_array_by_reference() const
{
return demPMFs;
}
const array_row* return_first_row_by_pointer() const
{
return demPMFs;
}
const array_t* return_array_by_pointer() const
{
return &demPMFs;
}
And here are the use cases:
SimPars foo;
double a = foo.return_array_by_reference()[0][0];
double b = foo.return_first_row_by_pointer()[0][0];
double c = (*foo.return_array_by_pointer())[0][0];
How would I return just the nth row of the array?
Again, you have three choices:
const array_row& return_nth_row_by_reference(size_t row) const
{
return demPMFs[row];
}
const double* return_first_element_of_nth_row_by_pointer(size_t row) const
{
return demPMFs[row];
}
const array_row* return_nth_row_by_pointer(size_t row) const
{
return demPMFs + row;
}
const double (* get_demPMFs() const)[INIT_NUM_AGE_CATS];
Or, use typedef (but that doesn't seems cleaner...).
class SimPars {
typedef const double (*ConstDemPMFType)[INIT_NUM_AGE_CATS];
double demPMFs[NUM_SOCIODEM_FILES][INIT_NUM_AGE_CATS];
public:
ConstDemPMFType get_demPMFs() const;
};
Note that you can't return an array (g++ refuses the compile). But an array of array can be decayed to a pointer to array, so the latter is returned.
Logically speaking there is this question with a data member. Should users be allowed to modify it or not. If you want to give another class full access to the member, you don't necessarily need getter/setter, especially if you are the only user. You can just make the member public.
If your class would be better off controlling how users access the member, then you could use a getter only to enforce read only access. The simplest way to do this if you don't want to get all confused about the 2-dimensional arrays is to just have an inline function fetching the element for the user class:
const double& getElem( int x, int y ) const { return demPMF[x][y] }
It makes sense to do bounds checking here, but considering that you insist on using arrays, and if your profiler proves that you can't afford it, this function would just allow access to your array.
If you want further elaboration, post a comment...

Passing pointer to 2D array c++

I'm having this problem for quite a long time - I have fixed sized 2D array as a class member.
class myClass
{
public:
void getpointeM(...??????...);
double * retpointM();
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A ); ???
A = moo.retpointM(); ???
}
I'd like to pass pointer to M matrix outside. It's probably very simple, but I just can't find the proper combination of & and * etc.
Thanks for help.
double *A[3][3]; is a 2-dimensional array of double *s. You want double (*A)[3][3];
.
Then, note that A and *A and **A all have the same address, just different types.
Making a typedef can simplify things:
typedef double d3x3[3][3];
This being C++, you should pass the variable by reference, not pointer:
void getpointeM( d3x3 &matrix );
Now you don't need to use parens in type names, and the compiler makes sure you're passing an array of the correct size.
Your intent is not clear. What is getpointeM supposed to do? Return a pointer to the internal matrix (through the parameter), or return a copy of the matrix?
To return a pointer, you can do this
// Pointer-based version
...
void getpointeM(double (**p)[3][3]) { *p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(double (*&p)[3][3]) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
For retpointM the declaration would look as follows
...
double (*retpointM())[3][3] { return &M; }
...
int main() {
double (*A)[3][3];
A = moo.retpointM();
}
This is rather difficult to read though. You can make it look a lot clearer if you use a typedef-name for your array type
typedef double M3x3[3][3];
In that case the above examples will transform into
// Pointer-based version
...
void getpointeM(M3x3 **p) { *p = &M; }
...
int main() {
M3x3 *A;
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(M3x3 *&p) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
// retpointM
...
M3x3 *retpointM() { return &M; }
...
int main() {
M3x3 *A;
A = moo.retpointM();
}
The short answer is that you can get a double * to the start of the array:
public:
double * getMatrix() { return &M[0][0]; }
Outside the class, though, you can't really trivially turn the double * into another 2D array directly, at least not in a pattern that I've seen used.
You could create a 2D array in main, though (double A[3][3]) and pass that in to a getPoint method, which could copy the values into the passed-in array. That would give you a copy, which might be what you want (instead of the original, modifiable, data). Downside is that you have to copy it, of course.
class myClass
{
public:
void getpointeM(double *A[3][3])
{
//Initialize array here
}
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A );
}
You may want to take the code in your main function which works with the 2D array of doubles, and move that into myClass as a member function. Not only would you not have to deal with the difficulty of passing a pointer for that 2D array, but code external to your class would no longer need to know the details of how your class implements A, since they would now be calling a function in myClass and letting that do the work. If, say, you later decided to allow variable dimensions of A and chose to replace the array with a vector of vectors, you wouldn't need to rewrite any calling code in order for it to work.
In your main() function:
double *A[3][3];
creates a 3x3 array of double* (or pointers to doubles). In other words, 9 x 32-bit contiguous words of memory to store 9 memory pointers.
There's no need to make a copy of this array in main() unless the class is going to be destroyed, and you still want to access this information. Instead, you can simply return a pointer to the start of this member array.
If you only want to return a pointer to an internal class member, you only really need a single pointer value in main():
double *A;
But, if you're passing this pointer to a function and you need the function to update its value, you need a double pointer (which will allow the function to return the real pointer value back to the caller:
double **A;
And inside getpointM() you can simply point A to the internal member (M):
getpointeM(double** A)
{
// Updated types to make the assignment compatible
// This code will make the return argument (A) point to the
// memory location (&) of the start of the 2-dimensional array
// (M[0][0]).
*A = &(M[0][0]);
}
Make M public instead of private. Since you want to allow access to M through a pointer, M is not encapsulated anyway.
struct myClass {
myClass() {
std::fill_n(&M[0][0], sizeof M / sizeof M[0][0], 0.0);
}
double M[3][3];
};
int main() {
myClass moo;
double (*A)[3] = moo.M;
double (&R)[3][3] = moo.M;
for (int r = 0; r != 3; ++r) {
for (int c = 0; c != 3; ++c) {
cout << A[r][c] << R[r][c] << ' ';
// notice A[r][c] and R[r][c] are the exact same object
// I'm using both to show you can use A and R identically
}
}
return 0;
}
I would, in general, prefer R over A because the all of the lengths are fixed (A could potentially point to a double[10][3] if that was a requirement) and the reference will usually lead to clearer code.

Problem passing a list of objects to another class, C++

Below I have written a sample program that I have written to learn about passing a list of objects to another class. I talk about the problems I am having below.
#include <iostream>
#include <vector>
using namespace std;
class Integer_Class
{
int var;
public:
Integer_Class(const int& varin) : var(varin) {}
int get_var() { return var; }
};
class Contains_List
{
typedef Integer_Class* Integer_Class_Star;
Integer_Class_Star list;
public:
Contains_List(const Integer_Class_Star& listin) : list(listin) {}
Integer_Class* get_list() { return list; }
};
int main (int argc, char * const argv[])
{
// Create a vector to contain a list of integers.
vector<Integer_Class> list;
for(int i = 0; i < 10; i++)
{
Integer_Class temp_int(i);
list.push_back(temp_int);
}
This is where the errors start occuring. Could someone please look at the second class definition and the code below and shed some light on what I'm doing wrong. Thank you so much, as always!
// Import this list as an object into another object.
Contains_List final(list);
// Output the elements of the list by accessing it through the secondary object.
for(int i = 0; i < 10; i++)
{
cout << final.get_list()[i].get_var();
}
return 0;
}
You don't mention what sort of errors you are getting, but one very obvious problem with your code is that the constructor for Contains_List expects a pointer to Integer_Class while the parameter you are sending it (list) is of type vector<Integer_Class>.
A vector is not the same as an array, so you cannot pass it as pointer to the type it contains. Either change your constructor to accept a vector or pointer/reference to vector, or change the code that is causing you problems so that it sends it a pointer to an array.
The 'Contains_List' constructor takes in an 'Integer_Class*'
You declare 'list' to be of type 'vector', yet you pass it to the the 'Contians_List' constructor. You should change the 'Contains_List' class so that it holds a vector instead of an Integer_List array. The two are not interchangeable.
You could also change the vector to be an array of Integer_List's instead, if you so wished.