The problem is C++ does not allow namespace declarations within classes.(I searched on internet and found this; if it's not true, please say it) So, what's the best way to cheat this problem?
Context: My class have an enumeration within it.
class GameCharacter {
public:
enum MovingState {
Running,
Walking,
Stopped
};
...
};
OBS: This example is not real, it's totally hypothetical.
C++ defines that the enumeration names are inside the class scope, then to use these states I have to use the scope operator directly from the class name(GameCharacter::Running
, for instance; or using GameCharacter::Running
).
I think this is bad, because the name which belongs to the enumeration is inside the class scope; I wanted to have a scope for the RunningState enumeration. (accessing it this way: GameCharacter::MovingState::Running
)
My first thought, then, was to create a namespace which would define a scope for the enumeration.
class GameCharacter {
public:
// does not compile
namespace MovingState {
enum State {
Running,
Walking,
Stopped
};
};
...
};
But C++ forbids it. This code does not compile. (main.cpp:3:5: error: expected unqualified-id before ‘namespace’
)
The reason why I'm trying to do things this way is because there is a possibility to create an second enumeration with names in same scope. Which could cause conflicting names.
class GameCharacter {
public:
enum MovingState {
Running,
Walking,
Stopped
};
enum DrivingState {
Accelerating,
Breaking,
Stopped // Compilation error: conflicts with previous declaration ‘GameCharacter::MovingState GameCharacter::Stopped’
};
...
};
(my idea was that, in this case, the states should be referred as GameCharacter::MovingState::Stopped
and GameCharacter::DrivingState::Stopped
)
Then, what should I do?
In C++1x (the new version of C++ that was standardised last year), you can use strongly typed enumerations, which put the identifiers in the scope of the enum class itself (among other improvements). These are declared with enum class
:
class GameCharacter {
public:
enum class State {
Running,
Walking,
Stopped // Referred to as GameCharacter::MovingState::Stopped.
};
...
};
In the meantime, if you're stuck with a C++03 compiler or want to retain compatibility, just use class
instead of namespace
and declare the constructor private as you suggested in your own answer. You can make the entire class
private if the outside world doesn't need to see it.
Try using new C++11 feature - strongly typed enumerations. Thanks to it you will not have name collisions and you will end up with really strong type system.
You can use enum class for this
enum class State
{
Accelerating,
Breaking,
Stopped
};
Then you'd refer to it as State::Breaking as you wanted.
This of course requires c++11, see http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations
An alternative I found was to, instead of namespace, use classes, but the problem is this way the project is not clear enough and classes can be instantiated. (Although I can cheat this problem with private constructors)
class GameCharacter {
public:
class MovingState {
MovingState();
/* or, in C++11:
* MovingState() = delete;
*/
public:
enum State {
Running,
Walking,
Stopped // Referred as GameCharacter::MovingState::Stopped.
};
};
class DrivingState {
DrivingState();
/* or, in C++11:
* DrivingState() = delete;
*/
public:
enum State {
Accelerating,
Breaking,
Stopped // Referred as GameCharacter::DrivingState::Stopped.
};
};
...
};
this works, but I'm not very clear if this is the best solution. I think there should be another way. I want opinions. What do you think?
This sounds like a job for C++11's Strongly Typed Enumerations.
class GameCharacter {
public:
enum class MovingState {
Running,
Walking,
Stopped
};
...
void f(Movingstate m) { if (m == MovingState;:Running) ... }
};
void f() { if (mm == GameCharacter::MovingState::Running) ... }
If you use C++11, you can use
class GameCharacter {
public:
enum class DrivingState { Accelerating, Breaking, Stopped };
enum class WalkingState { Stopped, Running, Walking };
DrivingState driving_state() { return ds_; }
void set_driving_state(DrivingState ds) { ds_ = ds; }
WalkingState walking_state() { return ws_; }
void set_walking_state(WalkingState ws) { ws_ = ws; }
DrivingState ds_;
WalkingState ws_;
};
int main() {
GameCharacter g;
g.set_walking_state(GameCharacter::WalkingState::Stopped);
g.set_driving_state(GameCharacter::DrivingState::Stopped);
return 0;
}
You can use a struct instead of a namespace if you are unable to use C++11 strongly typed enums:
class GameCharacter {
public:
struct MovingState {
enum Enum {
Running,
Walking,
Stopped
};
}
...
};
This was something that we adopted for a while (until C++11 support) as it can be used everywhere unlike the namespace trick.
If you have so much in your class that you feel you need to sub-categorise it into namespaces, then your class has too many things.
You should move stuff out of it. In particular all these enums don't need to be members of a class. Why not keep them in the same namespace that the class is in?