The task is to add data or values to members of a given enum class. The compiler should check if a value for each enum member is available, and not just the default constructor empty values. It is a tool to verify that no values are forgotten during a change.

The interface is modeled after the array of enumeration type in Delphi/Pascal which I find very useful.

Since I'm interested to learn about library design, I guess the interface is the important part:

template<typename Enum, typename T>
class enum_array {
  typedef typename std::array<T, enum_length<Enum>::result>::const_iterator
  typedef typename std::array<T, enum_length<Enum>::result>::iterator iterator;
  typedef T value_type;

  template<typename ... Args>
  enum_array(Args ... list);

  template<typename otherEnum>
  enum_array(const enum_array<otherEnum, value_type> &other );

  template<typename otherEnum>
  enum_array(enum_array<otherEnum, value_type> &&other );

  template<typename otherEnum>
  enum_array<Enum, value_type>& operator= (const enum_array<otherEnum, value_type> &other);

  template<typename otherEnum>
  enum_array<Enum, value_type>& operator= (enum_array<otherEnum, value_type> &&other);

  constexpr size_t size() const;

  // read values
  const value_type& at(int index) const;

  const value_type& operator[](int index) const;

  const value_type& at(Enum type) const;

  const value_type& operator[](Enum type) const;

  value_type& at(int index);

  value_type& operator[](int index);

  value_type& at(Enum type);

  value_type& operator[](Enum type);

  // write values
  void set_value(int index, const value_type &value);

  void set_value(Enum type, const value_type &value);

  // iterator access
  iterator begin();

  iterator end();

  const_iterator begin() const;

  const_iterator end() const;

  // algorithms
  Enum find(const value_type &value) const;

  Enum find(const value_type &value, Enum default_value) const;

I provided copy and move constructors, and assignment operators, with the compile time checks mentioned above, as well as value and iterator access.

To have it working, one needs to publish the size of an enum class which is done by these two macros:

#define DEF_ENUM(name, ...)                                                    \
  enum class name : uint8_t { __VA_ARGS__ };                                   \

#define SETUP_ENUM_LENGTH(enum_type, length)                                   \
  template<> struct enum_length<enum_type> { enum { result = length }; };

A use case looks like this:

DEF_ENUM(Columns, name, address, city, country)

// Does not compile, and tells you that the count is not right.
enum_array<Columns, std::string> Columntitle_bad {"Name", "Address", "City"};
// Compiles.
enum_array<Columns, std::string> Columntitle {"Name", "Address", "City", "Country"};
  • 4
    \$\begingroup\$ One common solution for this kind of problems is to use X-macros. Well used, you know that the number of elements will be the same. \$\endgroup\$ – Morwenn Nov 11 '13 at 23:10
  • 2
    \$\begingroup\$ @Morwenn: Thank you, I didn't know this idiom. However, to me it doesn't seem very save or natural compared to a enum value. At least not like we want modern C++11 to be. \$\endgroup\$ – Mike M Nov 11 '13 at 23:40
  • 4
    \$\begingroup\$ Sounds like you're looking for n3815 or maybe the more general n3814 to become real. (See also isocpp's mention) \$\endgroup\$ – Michael Urman Nov 12 '13 at 3:15
  • 6
    \$\begingroup\$ There is actually nothing here to review. The actual code is missing as are some other parts like the definition of enum_length.Voting to close. \$\endgroup\$ – Martin York Mar 28 '17 at 18:52
  • 3
    \$\begingroup\$ This question was discussed on meta. \$\endgroup\$ – Zeta Mar 30 '18 at 15:40