1

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?

starblue
  • 55,348
  • 14
  • 97
  • 151
Leonardo Raele
  • 2,400
  • 2
  • 28
  • 32

8 Answers8

3

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.

Mateusz Pusz
  • 1,363
  • 1
  • 9
  • 16
3

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

jcoder
  • 29,554
  • 19
  • 87
  • 130
2

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?

Leonardo Raele
  • 2,400
  • 2
  • 28
  • 32
2

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.

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169
1

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) ... }
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
1

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;
}   
rici
  • 234,347
  • 28
  • 237
  • 341
1

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.

0

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?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • GRASP Patterns. Does not make sense moving the enum away if it is used only in that class. EDIT: Also, just because a class have too much things does not necessarily means that it was bad designed. Classes can have a lot of responsibilities. – Leonardo Raele Nov 07 '12 at 16:29
  • @LeonardoRaele: Not necessarily. Sounds like a case of lumping everything into an object just because some design pattern told you to. You are in fact giving your object _too much responsibility_ by owning all these types. They belong in a namespace. You can make it so that it's a namespace containing only these enums and that class, if it makes you feel better... – Lightness Races in Orbit Nov 07 '12 at 16:31
  • `Also, just because a class have too much things does not necessarily means that it was bad designed.` Yes, by definition of "too much", that is _precisely_ what it means. – Lightness Races in Orbit Nov 07 '12 at 16:32