11

A using declaration does not seem to work with an enum type:

class Sample{
    public:
        enum Colour {RED, BLUE, GREEN};
}

using Sample::Colour;

does not work!

Do we need to add a using declaration for every enumerators of enum type? Like below:

using sample::Colour::RED;
5
  • Is there any other way to do this Commented Jan 13, 2009 at 7:22
  • 1
    Not really relevant to your question per se but I would strongly advise you not to use all-uppercase identifiers for enums and constants. Preprocessor #defines are usually all-uppercase in C/C++ and they -will- mangle other symbols with the same name. Commented Jan 13, 2009 at 10:05
  • Using the scope resolution operator :: on enums (as in "sample::Colour::RED") is a compiler-specific extension, not standard C++. Commented Jan 13, 2009 at 17:50
  • To see more about what bk1e said on this being non-standard, see this stack overflow question: Scope resolution operator on enums a compiler-specific extension? Commented Jan 25, 2018 at 0:00
  • 2
    @Jonathan Gawrych: The linked question is from '09 and the answers there no longer apply in '18. Commented Feb 28, 2019 at 17:27

4 Answers 4

11

To add to Steve Lacey's answer, the problem with the original code is that you refer to a member, but the using declaration is not itself a member declaration:

7.3.3/6 has:

A using-declaration for a class member shall be a member-declaration.

To highlight this, the following example does work:

class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

class Derived : public Sample
{
public:
  using Sample::Colour;  // OK
};

Finally, as pointed out by Igor Semenov, even if you move the enum definition into a namespace, thereby allowing the using declaration, the using declaration will only declare the name of the enum type into the namespace (the 2003 standard reference is 7.3.3/2).

namespace Sample
{
  enum Colour { RED,BLUE,GREEN};
}

using Sample::Colour;
using Sample::BLUE;


void foo ()
{
  int j = BLUE; // OK
  int i = RED;  // ERROR
}

Dependent Base Types

To allow for partial and explicit specializations, when the compiler parses a class template. it does not perform any lookups in dependent base classes. As a result, the following variation with Sample as a template does not compile:

template <typename T>
class Sample
{
public:
  enum Colour { RED,BLUE,GREEN};
};

template <typename T>
class Derived : public Sample<T>
{
public:
  using Sample<T>::Colour;  // What kind of entity is Colour?

  Colour foo ()     // Not OK!
  {
  return this->RED;
  }
};

The problem is that Derived::Colour is treated as an object by the compiler (14.6/2):

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

Looking at the two conditions for the name to be a type:

  1. Lookup for Colour doesn't find a type because the dependent base Sample<T> is not searched.
  2. The name is not qualified by typename

The example therefore needs the typename keyword:

template <typename T>
class Derived : public Sample<T>
{
public:
  using typename Sample<T>::Colour;  // Colour is treated as a typedef-name

  Colour foo ()  // OK
  {
  return this->RED;
  }
};

Note: The 1998 version of the standard didn't allow typename to be used with a using declaration and so the above fix was not possible. See Accessing types from dependent base classes and CWG11.

Sign up to request clarification or add additional context in comments.

1 Comment

In your first example, can you explain why the sample does not work with template <typename T> class Sample and template <typename T> class Derived : public Sample<T>?
10

A class does not define a namespace, and therefore "using" isn't applicable here.

Also, you need to make the enum public.

If you're trying to use the enum within the same class, here's an example:

class Sample {
 public:
  enum Colour { RED, BLUE, GREEN };

  void foo();
}

void Sample::foo() {
  Colour foo = RED;
}

And to access it from outside the class:

void bar() {
  Sample::Colour colour = Sample::RED;
}

1 Comment

A class, among other things, functions also as a namespace. Anything that works with ordinary namespaces but not with classes is therefore surprising.
5

C++ Standard, 7.3.3.1:

The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears. [ Note: only the specified name is so declared; specifying an enumeration name in a using-declaration does not declare its enumerators in the using-declaration’s declarative region. —end note ]

4 Comments

C++ Standard or A Night at the Opera? (Sorry, couldn't resist).
Could you explain me this idiom, I'm not very strong in English? :)
I am not sure the standard is written in English. Looks a lot like lawyer speak :-)
Actually, I meant "C++ Standard or A Night at the Opera?"
5

By now, there's a related question: 'using enum' in C++20.

It looks like C++20 will have the option make a using enum declaration, thus finally allowing direct access to an enum class' members, like this (source):

enum class fruit {
    orange,
    apple,
};

struct S {
  using enum fruit;             // OK, introduces orange and apple into S
};
void f() {
  S s;
  s.orange;                     // OK, names fruit​::​orange
  S::orange;                    // OK, names fruit​::​orange
}

Of course, that means that inside S, you will also be able to simply use orange and apple instead of fruit::orange and fruit::apple.

2 Comments

It is 2021. Perhaps update the answer (without "Edit:", "Update:", or similar - the question/answer should appear as if it was written today)?
I don't see the point in that, especially, because the content would stay exactly the same. Is that a SO thing?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.