问题
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;
回答1:
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;
}
回答2:
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:
- Lookup for
Colour
doesn't find a type because the dependent baseSample<T>
is not searched. - 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.
回答3:
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:
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
.
来源:https://stackoverflow.com/questions/438192/using-declaration-with-enum