E
Edson Tadeu
I was thinking in a way to do static dispatching on enumerations, in a
way similar to dispatching on integral constants using Loki's
Int2Type<> or Boost.MPL's int_<>, i.e, creating types based on the
enumeration constants, so I came up with this example code:
#include <iostream>
using namespace std;
template <class EnumType>
struct enum_ {
typedef enum_<EnumType> type;
typedef EnumType value_type;
};
template <class EnumType, EnumType EnumValue>
struct enumerator_ : public enum_<EnumType> {
typedef typename enumerator_<EnumType, EnumValue> type;
typedef typename enum_<EnumType>::value_type value_type;
enum {value = EnumValue};
operator EnumType() const { return EnumValue; }
};
namespace f {
enum Fruit { Apple, Banana, Cherry };
typedef enumerator_<Fruit, Apple> AppleType;
typedef enumerator_<Fruit, Banana> BananaType;
typedef enumerator_<Fruit, Cherry> CherryType;
// helper constants
static const AppleType AppleTag;
static const BananaType BananaTag;
static const CherryType CherryTag;
// a helper -- we don't have template typedef yet
template <Fruit F> struct tag : public enumerator_<Fruit, F>
{};
};
void Eat(f::AppleType, int number) {
cout << "Eating " << number << " apples." << endl;
}
void Eat(f::BananaType, int dozens) {
cout << "Eating " << 12 * dozens << " bananas!" << endl;
}
void Eat(f::CherryType, int number) {
cout << "Eating " << number << " cherries." << endl;
}
int main()
{
Eat(f::tag<f::Apple>(), 3);
Eat(enumerator_<f::Fruit, f::Banana>(), 2);
Eat(f::CherryTag, 10);
return 0;
}
Output is:
Eating 3 apples.
Eating 24 bananas!
Eating 10 cherries.
Of course this is a silly example and not so useful, but it would be
more useful in situations involving template parameters or static
dispatching to constructors.
One of the problems in this solution is that it involves a lot of
repetition (each enumerator name was declared three times.. e.g, Apple,
AppleType and AppleTag).
What do you think of this solution? Is it 'legal'? How can it be
improved?
way similar to dispatching on integral constants using Loki's
Int2Type<> or Boost.MPL's int_<>, i.e, creating types based on the
enumeration constants, so I came up with this example code:
#include <iostream>
using namespace std;
template <class EnumType>
struct enum_ {
typedef enum_<EnumType> type;
typedef EnumType value_type;
};
template <class EnumType, EnumType EnumValue>
struct enumerator_ : public enum_<EnumType> {
typedef typename enumerator_<EnumType, EnumValue> type;
typedef typename enum_<EnumType>::value_type value_type;
enum {value = EnumValue};
operator EnumType() const { return EnumValue; }
};
namespace f {
enum Fruit { Apple, Banana, Cherry };
typedef enumerator_<Fruit, Apple> AppleType;
typedef enumerator_<Fruit, Banana> BananaType;
typedef enumerator_<Fruit, Cherry> CherryType;
// helper constants
static const AppleType AppleTag;
static const BananaType BananaTag;
static const CherryType CherryTag;
// a helper -- we don't have template typedef yet
template <Fruit F> struct tag : public enumerator_<Fruit, F>
{};
};
void Eat(f::AppleType, int number) {
cout << "Eating " << number << " apples." << endl;
}
void Eat(f::BananaType, int dozens) {
cout << "Eating " << 12 * dozens << " bananas!" << endl;
}
void Eat(f::CherryType, int number) {
cout << "Eating " << number << " cherries." << endl;
}
int main()
{
Eat(f::tag<f::Apple>(), 3);
Eat(enumerator_<f::Fruit, f::Banana>(), 2);
Eat(f::CherryTag, 10);
return 0;
}
Output is:
Eating 3 apples.
Eating 24 bananas!
Eating 10 cherries.
Of course this is a silly example and not so useful, but it would be
more useful in situations involving template parameters or static
dispatching to constructors.
One of the problems in this solution is that it involves a lot of
repetition (each enumerator name was declared three times.. e.g, Apple,
AppleType and AppleTag).
What do you think of this solution? Is it 'legal'? How can it be
improved?