Boost logo

Boost :

From: christopher diggins (cdiggins_at_[hidden])
Date: 2005-06-17 13:11:29


----- Original Message -----
From: "Maksym Motornyy" <mmotorny_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, June 17, 2005 11:47 AM
Subject: [boost] Typesafe enums proposal

> Hello, all.
>
> I want to propose typesafe enums. Sources are available in Boost Sandbox
> (typesafe_enums.zip). Were tested under VC 7.1.

Thank you for sharing your code.

> Main features are:
> - type safety;
> - meaningful printable names;

I think that the names are only "meaningful" if the source language and the
application user's language are the same. In general this kind of ability is
useful in debugging but in real applications the restraints on identifiers
is too limiting (i.e. no punctuation, no accents, no spaces). Far more
powerful would be the ability to associate arbitrary data with an enum. This
I believe is relatively easy to add to your framework.

[snip
>
> Is anybody found it useful?

Yes I think it would be useful.

> Sincerely,
> Maksym Motornyy.

I wish to state for the record, I believe macros should only be used as a
last resort. I agree that they make certain tasks more convenient but the
following coding pardadigm for implementing enums works almost as well,
except that it lacks "meaningful names":

template<typename T, int N>
struct enumerator {
  const static int value = N;
  typedef enumerator<T, N + 1> next;
};

struct weekday
{
  // self typedef
  typedef weekday self;

  // 'ctors
  template<int N>
  weekday(const enumerator<self, N>& x) : value(N) { }
  weekday(const self& x) : value(x.value) { }

  // enumerations
  typedef enumerator<self, 0> mon;
  typedef mon::next tue;
  typedef tue::next wed;
  typedef wed::next thu;
  typedef thu::next fri;
  typedef fri::next sat;
  typedef sat::next sun;
  typedef sun::next end_day;

  // operators
  self& operator++(int) { ++value; return *this; }
  self& operator--(int) { --value; return *this; }
  self operator++() { self tmp = *this; ++value; return tmp; }
  self operator--() { self tmp = *this; --value; return tmp; }
  friend bool operator==(const weekday& x, const weekday& y) { return
x.value == y.value; }
  friend bool operator!=(const weekday& x, const weekday& y) { return
x.value != y.value; }
  operator int() const { return value; }

  // static functions
  static mon begin() { return mon(); }
  static end_day end() { return end_day(); }

  // fields
  int value;
};

void weekday_reaction(const weekday& x) {
  switch (x)
  {
    case (weekday::mon::value) :
      std::cout << "doh! monday" << std::endl;
      break;
    case (weekday::tue::value) :
      std::cout << "doh! tuesday" << std::endl;
      break;
    case (weekday::wed::value) :
      std::cout << "doh! hump-day" << std::endl;
      break;
    case (weekday::thu::value) :
      std::cout << "woohoo! day before friday" << std::endl;
      break;
    case (weekday::fri::value) :
      std::cout << "woohoo! friday" << std::endl;
      break;
    case (weekday::sat::value) :
      std::cout << "woohoo! saturday" << std::endl;
      break;
    case (weekday::sun::value) :
      std::cout << "doh! church!" << std::endl;
      break;
    default:
      std::cout << "whatcha talkin' 'bout willis?" << std::endl;
      break;
  }
}

int main()
{
  weekday_reaction(weekday::sat());
  // weekday_reaction(42); does not compile
  weekday_reaction(weekday::end());

  for (weekday wd = weekday::begin(); wd != weekday::end(); wd++) {
    weekday_reaction(wd);
  }

  system("pause");
  return 0;
}

Comparing this to your macro technique, using macros is much more compact
and convenient. I for one would not use macros for enums, but I think your
library has potential:

Christopher Diggins
http://www.cdiggins.com


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk