I'm practicing different ways of class design, so I'd like feedback on the design characteristics. Of course code practice comments are also welcome.It was a conscious decision to omit templates. My next version will use a class template to store image data, similar to CImg and boost::GIL. I intend to make more classes with increasing complexity (templates, abstract base class, variadic templates). Until I reach a detailed yet highly abstract image class.Header:#ifndef AIMG#define AIMG#include <vector>#include <string>class AImg{public:  const std::vector<short> dimsizes; //or std::array of length 4?  const int N;     //# of elements ( = product of dimension sizes)  unsigned int Bytes {1}; //bytes per element  std::string tag; //meta info like rgb  std::string cast;//used for returning data of type cast  void* data;      //pointer to some array/container/byte-blob  AImg(const std::vector<short>&); //you have to specify image size when creating. But may be empty of data.  void setdata(void*);  void* getdata();  //example of pseudo-template method:  void plusone(std::string);  int operator()(unsigned int); //variable args would allow better indexingprivate:  int getN();  //checkcast() ?};//public fcnsAImg::AImg(const std::vector<short>& input): dimsizes(input), N(getN()), cast() {}int AImg::operator()(unsigned int idx){   if (cast==int)    {return ((int*)data)[idx];} else return 0;  }void  AImg::setdata(void* input){data=(void*)input;}void* AImg::getdata(){return data;}void  AImg::plusone(std::string cast){        if (cast==int)        {          int* idata = (int*)data;          for (int i = 0;i<N;i++){idata[i] += 1;}        }        else if (cast == float)        {          float* fdata = (float*)data;          for (int i = 0;i<N;i++){fdata[i] += 1.0;}        }        //...other types        // careful: N is based on elements of some user-defined type. Not all types have the same precision (#bytes).        // So you'd need to normalize N based on the type size ( sizeof() ) to properly iterate over the data, or forbid certain types      }//Private fcnsint AImg::getN(){ //doesn't STL have a std::prod() ?!?!  int prod = 1;  for(short n : dimsizes) prod *= n;  return prod;}#endif // AIMGMain:#include <iostream>#include AImg.husing std::cout;  using std::cin;using std::endl;  using std::vector;int main(){  //create image object of size 2x2AImg img(vector<short> {2,2});  //create image data: simple int arrayint d[4] {1,2,3,4};img.setdata(d); //make sure length of d equals N, i.e. fill img up completelyimg.plusone(int);int* d2 = (int*)img.getdata(); //need to explicitly re-cast in c++cout<<d2[0]<<d2[1]<<d2[2]<<d2[3]<<endl;img.cast = int;cout<<img(0)<<img(1)<<img(2)<<img(3)<<endl;}Personally I think a class design like this is risky to use, so should I add more safety checks? It also seems harder to maintain and extend compared to a class using templates.It also seems hard to extend the model to allow for inhomogenous (sub)pixels. For example, the value of a pixel at (1,1,1) could be an int but the value of the pixel at (1,1,2) could be an unsigned char.
Engineering a minimalist image interface without templates
c++;design patterns;image;library