28

In a rock, paper, scissors program that I am writing, I am enumerating the three different moves and declaring them as a class. However, when I try to write a using statement so that I have to avoid using the scope operator, it doesn't seem to work. Anyone know why?

enum class choice {rock, paper, scissors};

using namespace choice;

Here an error message comes up, saying: [Error] 'choice' is not a namespace name. Why is this? I thought that for choice could be a namespace, in this context.

0

8 Answers 8

43

It will be possible in C++20, P1099R5 :

enum class choice {rock, paper, scissors};

using enum choice;
Sign up to request clarification or add additional context in comments.

Comments

10
namespace choice
{
    enum class type {rock, paper, scissors};
    constexpr auto rock     = type::rock    ;
    constexpr auto paper    = type::paper   ;
    constexpr auto scissors = type::scissors;
}

int main()
{
    choice::type move;
    using namespace choice;
    move = rock;
    move = paper;
    move = scissors;

    return 0;
}

Comments

4

The behaviour you want can be achieved with namespace choice { enum choice { ... }; }. It will work only for values though, you still have to use choice::choice if you want to declare a variable. Unless you also use auto, of course.

1 Comment

namespace choice { enum type { ... }; }, then choice::type move = choice::rock;
3

This may be a very old question, but to extend on @catscradle's answer and @anton_rh's comment, you can make it even more convenient if you add a 'using' statement to make a shortcut for the choice::choice:

namespace choice_values {
    enum type {
        rock,
        paper,
        scissors
    }
}
using choice = choice_values::type;

Now, you can use the enum as normal:

choice chosen_move = choice::rock;

but you can also avoid the scope operator if you use the choice_values namespace:

using namespace choice_values;
choice chosen_move = rock;

(I know this is probably better as a comment, but I don't have the reputation yet to do so...)

4 Comments

Your solution applies to normal enums, not class enums as the question specifies. Hence (I assume) the downvotes.
@phlummox That's not a great reason to downvote this, because the point of enum class is to avoid pollution, but Lut_99's suggestion also achieves this goal.
@allyourcode I'm not sure why you're responding to something I never said. I never said it was a great reason. I said I assume that's probably why it got downvotes. As it happens, I didn't downvote this. But looking at it again, perhaps I should.
@allyourcode The point of an enum class isn't merely to avoid pollution, it's also a matter of type safety. With your definition, choice chosen_move = 100; will compile but likely lead to a logic error elsewhere because a value of 100 does not correspond to rock, paper, or scissors, and any code presuming those are the only values that exist will encounter problems. Had you used an enum class, that would cause an outright compiler error instead because int and choice would be incompatible types, which would obviate the need to hunt down a potentially subtle bug.
1

If like below, I just use "typedef A::B::C C".

namespace A
{
    class B
    {
    public:
        enum class C : unsigned char
        {
            Something
        };
    };
}

Comments

0

I would do something similar to Lut_99 (but slightly different):

namespace choice_ns {
enum Choice { rock, paper, scissors };
}
using choice_ns::Choice;

bool beats(Choice a, Choice b) {
  using namespace choice_ns;
  switch (a) {
    case rock:
  // etc...
}

void does_not_compile() {
  rock;  // This requires qualification.
}

Notice that enum class is not used, but a similar effect is achieved: you MUST use the choice_ns:: prefix when saying rock. This avoids polluting the outer namespace, which is the main point of enum class. Also notice that, like enum class, you can refer to Choice WITHOUT the choice_ns:: prefix.

The name of the namespace is deliberately awkward, because the only time you need it is when you say using namespace ... at the beginning of your functions.

One difference between this and what Lut_99 suggests is that if you do it his way, declarations look like this:

choice::type a;

which is both verbose and awkward compared to my way:

Choice a;

Some of the other suggestions involve doing

constexpr SomeType rock = whatever::rock;

But this is really not great, because repetition, which means there's a good chance that you will make a mistake, especially if you decide to add values later on. E.g. https://www.youtube.com/watch?v=Kov2G0GouBw

I have been wanting this for a while. Good to see from Baptistou that this is going to be possible in the not too distant future. In the mean time, you can get something very similar using technology that's currently available today.

Comments

-1

choice isn't a namespace, so using namespace choice; isn't valid. If you don't want to have to use a scope designator, don't use a scoped enum. A plain enum will work for what you've mentioned so far:

enum choice { rock, paper, scissors };

3 Comments

hmm... Have you heard of the book C++ Without Fear by brian overland? In there, he claims that namespace can be used. Maybe I'm doing something wrong. Is there any way to avoid using a scoping operator while still declaring a scoped enum?
@user2457666 if you really want to use scoping operator then put the enum into a namespace.
If you use a regular enum inside a namespace (effectively recreating the "has its own scope" part of enum class with pre-C++11 functionality), then using namespace will work. This does lose out on the other benefits of enum class, though, namely the added type safety (and to a lesser extent the explicitly specified underlying type (or int by default), but that's available for normal enums too in C++11 (just without the explicit "defaults to int if not specified")).
-1
enum class choice {rock, paper, scissors}
rock = choice::rock, paper = choice::paper, scissors = choice::scissors;

1 Comment

This is difficult to maintain if there is a possibility that you might want to add more values to choice in the future. E.g. youtube.com/watch?v=Kov2G0GouBw

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.