21

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.

Victor Odouard
  • 1,345
  • 3
  • 15
  • 28

8 Answers8

28

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

enum class choice {rock, paper, scissors};

using enum choice;
Baptistou
  • 1,749
  • 1
  • 13
  • 24
8
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;
}
allyourcode
  • 21,871
  • 18
  • 78
  • 106
anton_rh
  • 8,226
  • 7
  • 45
  • 73
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.

catscradle
  • 1,709
  • 11
  • 18
1

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

namespace A
{
    class B
    {
    public:
        enum class C : unsigned char
        {
            Something
        };
    };
}
Sunny Mok
  • 11
  • 1
1

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...)

Lut_99
  • 13
  • 1
  • 5
  • Your solution applies to normal enums, not *class* enums as the question specifies. Hence (I assume) the downvotes. – phlummox Jan 17 '21 at 06:08
  • @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 May 19 '21 at 20:06
  • 1
    @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. – phlummox May 20 '21 at 04:08
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.

allyourcode
  • 21,871
  • 18
  • 78
  • 106
-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 };
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 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? – Victor Odouard Jun 07 '13 at 01:45
  • @user2457666 if you really want to use scoping operator then put the `enum` into a `namespace`. – mr5 Jun 07 '13 at 06:37
  • 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 `enum`s too in C++11 (just without the explicit "defaults to `int` if not specified")). – Justin Time - Reinstate Monica Sep 30 '19 at 02:06
-1
enum class choice {rock, paper, scissors}
rock = choice::rock, paper = choice::paper, scissors = choice::scissors;
Xiao
  • 1
  • 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. https://www.youtube.com/watch?v=Kov2G0GouBw – allyourcode May 19 '21 at 20:04