Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deduce array size from an enum template argument?

How should I change the code below so that Array<Index> array; is enough and the SIZE is automatically deduced from the enum?
Even if the enum changes, it is guaranteed that it contains SIZE referring to the correct size.

template <typename Enum, int N>
class Array {

public:
    int& operator[](Enum index) { return array[index]; }

private:
    int array[N];
};

enum Index { X, Y, SIZE };

int main() {

    Array<Index, SIZE> array;

    array[X] = 1;

    return 0;
}

UPDATE: As for "Array<type> means you're creating an array of Type objects" (Jerry) and "the name of class template is a bit misleading" (Nawaz): actually I am creating CustomSqlQueryModel<TableColumns>. The above is just a simplified code, nothing more. Jerry and Nawaz are rigth: this simplified code is unfortunate.

like image 666
Ali Avatar asked Feb 15 '11 00:02

Ali


2 Answers

You can write a traits class. This requires a bit of extra work each time you define a new enum type, but no extra work for each occurrence of Array<Index> in user code:

template<class Enum>
struct ArrayTraits;

template<class Enum>
struct Array {
  int& operator[](Enum index) { return array[index]; }

private:
  int array[ArrayTraits<Enum>::size];
};

enum Index { X, Y, SIZE };

template<>
struct ArrayTraits<Index> {
  enum { size = SIZE };
};


int main() {
  Array<Index> array;
  array[X] = 1;
  return 0;
}

One of the advantages of this is you can specialize the traits for external enums you don't control, as long as you know how to get the max size.

like image 50
Fred Nurk Avatar answered Nov 19 '22 01:11

Fred Nurk


As stated, I don't think you can. If, however, you change it to something like:

struct Index { 
    enum { X, Y, SIZE};
};

Then your template could be something like:

template <class Enum>
class Array { 
// ...

private:
    int array[Enum::SIZE];
};

...and if the type you pass as Enum doesn't include some positive constant named SIZE,the instantiation won't compile. For the purpose at hand, you'd really kind of prefer that Index was a namespace, but since a namespace isn't a type, I don't think you can use it as a template argument.

I should add, however, that I'm not sure I like this idea at all -- most people are going to think Array<type> means you're creating an array of Type objects, and this is clearly something entirely different from that...

like image 31
Jerry Coffin Avatar answered Nov 19 '22 01:11

Jerry Coffin