Yves Meynard's Enumeration class (CUJ Web exclusive, May 2003)

B

Brian Riis

This all pertains to the above mentioned article. Anyone want to read it
(it's rather neat, actually), here's the address:

http://www.cuj.com/documents/s=8205/cujweb0305meynard/

Anyway, I was trying to work my way through the idea of the class,
especially the one, that uses a template parameter for the enumeration
value, in the hopes of getting an enum that enumerated through std::strings.

The whole idea is to keep a base class with a static std::set<> of
pointers to static instantiations of a derived class. The whole shebang
designed using the Curiously Recurring Template Pattern (meaning that
the derived class passes itself as a template parameter to the base
class). Here's a simplified implementation (read the above link for full
details.

<code>

template <class T, class TValue>
class Enum
{
private:
// Actually needs a "less-than" predicate. Omitted here...
static std::set<Enum<T, TValue> *> s_instances;
TValue m_value;

protected:
explicit Enum(TValue const & value): m_value(value)
{
s_instances.insert(this);
}

public:
TValue const & get_value() const { return m_value; }

// ... more static functions follow to implement an STL-like
// interface to the enum; begin(), end(), size(), et al.
};

// instantiate the s_instances std::set<>
template <class T, class TValue>
typename std::set<Enum<T, TValue> *>
Enum<T, TValue>::s_instances;

// An actual "enum", enumerated on std::string
class Enum_String
: Enum<Enum_String, std::string> // <- Curiously Recurring Template
{
private:
explicit Enum_String(std::string const & value)
: Enum<Enum_String, std::string>(value){} // Base class "inserts"

public:
static const Enum_String Alpha;
static const Enum_String Beta;
// ... however many _valid_ values of Enum_String is needed...
};

// Instantiate the static "Enum_String"s
const Enum_String Enum_String::Alpha("Alpha");
const Enum_String Enum_String::Beta ("Beta");

</code>

Here's the problem. At the above instantiations, an anonymous
std::string ("Alpha") is constructed and passed to Enum_String's
constructor. (Pseudo-code)

Enum_String::Enum_String(std::string("Alpha"))

This constructor, in turn, passes the value to the instantiated base
class' constructor.

Enum<Enum_String, std::string>::Enum(std::string("Alpha"))

This constructor set the m_value member variable *and inserts a pointer
to this into the set*!!! Or at least it tries to.

Problem is, AFAIK, C++ does not guarantee that the s_instances variable
has been constructed at this time. Both s_instances and the
"Enum_String"s are constructed globally, but I believe that there is no
guarantee that s_instances is constructed first, making the construction
of Enum_String impossible (since the constructor relies on s_instances).

If I understand C++ rules correctly, this may work or not, as "the wind
blows", depending on whether the compiler decides to instantiate
s_instances first or not.

Now my question is: Is there a way to get around this problem, ie. make
sure that s_instances is constructed *before* any of the Enum_String
instances?

Or have I misunderstood completely? (always a possibility! :) )

Opinions and comments, please! :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top