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;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yesraaj
  • 46,370
  • 69
  • 194
  • 251
  • Is there any other way to do this – yesraaj Jan 13 '09 at 07: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. – Timo Geusch Jan 13 '09 at 10:05
  • Using the scope resolution operator :: on enums (as in "sample::Colour::RED") is a compiler-specific extension, not standard C++. – bk1e Jan 13 '09 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?](https://stackoverflow.com/q/441552/1248889) – jgawrych Jan 25 '18 at 00:00
  • 2
    @Jonathan Gawrych: The linked question is from '09 and the answers there no longer apply in '18. – AnT stands with Russia Feb 28 '19 at 17:27

4 Answers4

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Richard Corden
  • 21,389
  • 8
  • 58
  • 85
  • 1
    In your first example, can you explain why the sample does _not_ work with `template class Sample` and `template class Derived : public Sample`? – geometrian Jul 24 '15 at 03:42
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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Steve Lacey
  • 813
  • 8
  • 11
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 ]

Igor Semenov
  • 1,548
  • 9
  • 7
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.

RL-S
  • 734
  • 6
  • 21
  • It is [2021](https://en.wikipedia.org/wiki/C%2B%2B20). Perhaps [update the answer](https://stackoverflow.com/posts/58234069/edit) (***without*** "Edit:", "Update:", or similar - the question/answer should appear as if it was written today)? – Peter Mortensen Apr 02 '21 at 12:38
  • I don't see the point in that, especially, because the content would stay exactly the same. Is that a SO thing? – RL-S May 25 '21 at 10:57