using declaration with enum?

2019-01-20 10:21发布

using declaration does not seem to work with enum type

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

using Sample::Colour;

does not work!! do we need to add using declaration for every enumerators of enum type? like below

using sample::Colour::RED;

3条回答
劳资没心,怎么记你
2楼-- · 2019-01-20 10:40

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 ]

查看更多
甜甜的少女心
3楼-- · 2019-01-20 10:51

A class does not define a namespace, 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 without the class:

void bar() {
  Sample::Colour colour = Sample::RED;
}
查看更多
倾城 Initia
4楼-- · 2019-01-20 10:51

To add to Stevela'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 here, 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 '98 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.

查看更多
登录 后发表回答