Reputation: 13451
I have implemented custom class representing an enumeration possibilities similarily to this article:
// Color.h
class Color {
public:
static const Color Red;
static const Color Green;
static const Color Blue;
//...
private:
explicit Color(int code);
//...
int code;
static std::set<Color> colors;
};
// Color.cpp:
const Color Color::Red(1);
const Color Color::Green(2);
const Color Color::Blue(3);
//...
Now I have problem when I want to use instances of Color
e.g.: Color::Red
to initialize a global variable in another translation unit. I understand that it happens because it is not defined which translation unit global variables are initialized first. How the initialization ordering problem could be solved?
The only solution that I can think of is using nifty counter. But I am not able find out, how to use it without affecting syntax of the enumeration class. I was thinking about adding set()
method into Color
. Then I could call this method in a nifty counter like initializer:
// Color.h
class Color {
public:
void set(int code);
//...
private:
Color() { /* empty */}
//...
};
static class ColorInitializer {
ColorInitializer () {
static bool initialized = false;
if(initialized)
return;
Color::Red.set(1);
Color::Green.set(1);
Color::Blue.set(1);
initialized = true;
}
} colorInitializer;
// Color.cpp
const Color Color::Red;
const Color Color::Green;
const Color Color::Blue;
But the problem I see here is that the set
method could be called on object that is not yet constructed. Is that OK or is the behavior undefined? How to better solve the problem of undefined initialization order?
Upvotes: 0
Views: 1743
Reputation: 73480
Since your Colour objects are lightweight, just could just use static functions.
class Color {
public:
static Color Red() { return Color(1); }
static Color Green() { return Color(2); }
static Color Blue() { return Color( 3 ); }
private:
explicit Color(int code);
};
The only problem with this is you can not pass these objects, to functions expecting pointers or non-const references (but non-const references in this case is probably nonsensical anyway).
Upvotes: 2
Reputation: 94299
Don't use global objects in the first place. Instead, use functions:
class Color {
public:
static const Color &Red() {
static const Color c( 1 );
return c;
}
static const Color &Green() {
static const Color c( 2 );
return c;
}
static const Color &Blue() {
static const Color c( 3 );
return c;
}
private:
explicit Color(int code);
//...
};
You can now use these functions to initialize other objects; calling them will ensure that the constructor of the Color
objects is called.
Upvotes: 2
Reputation: 5127
In C++11 (if you can afford using it) you could use extended constant expression functionality:
class Color {
public:
static constexpr const Color Red;
static constexpr const Color Green;
static constexpr const Color Blue;
private:
constexpr explicit Color(int code);
//...
};
// Color.cpp:
constexpr Color Color::Red(1);
constexpr Color Color::Green(2);
constexpr Color Color::Blue(3);
//...
Upvotes: 3