I am creating a C++ class which wraps an floating point 2d array and provides some additional functionality. I want to pass the array's shape as parameters to the constructor, see the code (the class Block part) below. The line ends with comment "// here" would cause error during compilation because _nx and _ny are not known at that time. There are two solutions (I think) around this: one is using pointer (see solution 1 in the code below) and dynamically allocate the array; the other is using template (see solution 2 in the code below), but I have several reasons not to use them:
- I don't want to use pointer as long as there is a pointer-less option; in other words, I don't want to use new and delete. The reason for this is a personal preference for purer c++.
- I don't want to use template because there can be many different block shapes - I don't want the compiler to create many classes for each of them, this is an overkill and increases the executable size.
In addition, I don't want to use stl vector because the array size is fixed after creation; also I am doing numerical computation, so a 'raw' array suits me much better.
I have searched in SO and there are five or six questions asking similar problems, there is no conclusion which one is better though, and none of them are from a numerical standing point so vector or new/detele are good answers for them - but not for me. Another reason I post this question is I want to know if I am too restrictive in using c++ features. As I will be using c++ extensively, it's very important to be aware of c++'s limitation and stop asking/searching too much for some feature that doesn't exist.
#include <iostream>
#include <memory>
using namespace std;
class Block
{
public:
Block(int nx, int ny):_nx(nx),_ny(ny){}
void Report(void)
{
cout << "Block With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx, _ny;
double _data[_nx][_ny]; // here
};
/// Solution 1, using auto_ptr
class BlockAuto
{
public:
BlockAuto(int nx, int ny):_nx(nx),_ny(ny),_data(new double[_nx*_ny]){}
void Report(void)
{
cout << "BlockAuto With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx;
const int _ny;
const auto_ptr<double> _data;
};
/// Solution 2, using template
template<unsigned int nx, unsigned int ny>
class BlockTpl
{
public:
BlockTpl():_nx(nx),_ny(ny){}
void Report(void)
{
cout << "BlockTpl With Size ["<<_nx<<","<<_ny<<"]\n";
}
private:
const int _nx;
const int _ny;
double _data[nx][ny]; // uncomfortable here, can't use _nx, _ny
};
int main(int argc, const char *argv[])
{
Block b(3,3);
b.Report();
BlockAuto ba(3,3);
ba.Report();
BlockTpl<3,4> bt;
bt.Report();
return 0;
}