Use 'using enum' in C++20 in classes possible? - c++

In this answer it was mentioned that in the upcoming C++20 standard it is possible to use the using statement on enum class and import the enum fields into the local namespace.
I was wondering if that also means that I can also use it within class definitions like this:
class Foo {
enum class Color
{
red,
blue
};
using enum Color;
};
int main()
{
Foo::Color c = Foo::red;
}
Or do I still need to give the full namespace?:
Foo::Color c = Foo::Color::red;
I tried it in wandbox.org, but it seems that neither gcc nor clang know about using enum yet.

Yes, Foo::Red will work fine. using enum E behaves as, from [enum.udecl]:
A using-enum-declaration introduces the enumerator names of the named enumeration as if by a using-declaration for each enumerator.
And the standard contains an example of exactly this case:
[ Note: A using-enum-declaration in class scope adds the enumerators of the named enumeration as members to the scope. This means they are accessible for member lookup. [ Example:
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
}
— end example ] — end note ]
Note however that there is some controversy around the particular spelling for this feature. enum E is what's known as an elaborated type specifier (much like class C or struct S). Typically, elaborated type specifiers behave exactly the same was as their underlying versions. Elaborating is just meant to disambiguate, and you rarely need to disambiguate, so you wouldn't see it very often. However, in this particular case, using enum E and using E actually mean wildly different and wholly unrelated things. So keep in mind that there is a chance that this feature may not yet actually make C++20, despite currently being in the working draft and even having been published in the CD. As such, it's unlikely that compilers will implement this feature until they're sure it's necessary to implement (C++20 isn't exactly lacking in work for compiler writers...)

Related

Specifyin "enum" in a using statement - does it make a difference?

A "sanity check" question for language lawyers / nitpickers:
In this snippet of code:
enum my_enum { AValue1, AValue2 };
using alias_1 = enum my_enum;
using alias_2 = my_enum;
can there be any sort of difference between alias_1 and alias_2? That is, may a compiler treat them differently somehow? My best understanding is that the answer is "no", but a user of mine is experiencing different compiler behavior with the first kind rather than the second kind of statements, when using MSVC 16.8 + CUDA. Something like cannot convert argument 1 from 'my_enum' to 'alias_1'.
Notes:
Pathologies like #define enum or name hiding are relevant to address in answers, I suppose, but I'm mostly interested in a "non-pathological" situation.
Asking specifically regarding C++11 in case it matters.
I'm finding it difficult to create an MWE, since I don't have that compiler myself nor do I usually run Windows.
The only difference I can think of is that with the usage of the keyword enum (as in elaborated type specifier), the non-type names will be excluded from name lookup.
(emphasis mine)
The class-name or enum-name in the elaborated type specifier may either be a simple identifier or be a qualified-id. The name is looked up using unqualified name lookup or qualified name lookup, depending on their appearance. But in either case, non-type names are not considered.
E.g.
enum my_enum { AValue1, AValue2 };
int main()
{
int my_enum;
using alias_1 = enum my_enum; // works; refers to the enum my_enum
//using alias_2 = my_enum; // doesn't work; the non-type name my_enum in main() is found
}

Why doesn't clang allow accessing a nested enum class through an instance?

Consider the following code:
struct S {
enum class EnumClass {
one
} ;
enum Enum {
one
};
};
int main()
{
S s;
S::EnumClass e = s.EnumClass::one; // <- Doesn't compile with clang
S::Enum e11 = s.Enum::one;
S::Enum e12 = s.one;
}
Everything works with GCC, but clang (neither 3.8 nor 3.9) does not compile s.EnumClass::one, giving an error: 'S::EnumClass::one' is not a member of class 'S'.
Given the fact that unscoped enums work fine, it seems like a bug.
This is a bug in gcc1. The relevant wording is in [expr.ref]p2:
In either case, the id-expression [here: EnumClass::one] shall name a member of the class or of one of its base classes.
EnumClass::one does not refer to a member of a class, it's a member of an enum. It doesn't matter whether that enum is part of the class, it's just that the member one itself is not part of the class.
But is Enum::one part of the class? Yes, according to [class.member]p1:
Members of a class are data members, member functions, nested types, enumerators, and member templates and specializations thereof.
and made more explicit in [class.member]p3:
The enumerators of an unscoped enumeration defined in the class are members of the class.
1: I would even go as far as to call it a bug in the standard, as there doesn't seem to be any (technical) reason why this should be disallowed and I think it would be a good idea to allow it. There are talks about allowing it though, so let's see what the committee decides.

What's an enum class and why should I care?

For one who has never written a line of C++11, and who has, at the moment, no opportunity to program in C++11, can you, in one short paragraph., tell me:
What is an "enum class" and why do we need it?
enum class is called a scoped enumeration. It prevents polluting the namespace where the enumeration appears with the names of the enumerators.
In C++03, you could do effectively the same thing by putting the enum inside a dedicated class. Perhaps that's the source of the syntax, which is a bit confusing.
Another difference is that the enumerators of such a type don't convert implicitly to int (static_cast<int> is required). This may be seldom needed but it makes it safe to overload a function taking an int argument with one taking enum type. You can be sure the int won't be called by accident. Or you can define pseudo-integral types with dedicated operator functions, and be sure that built-in operators won't interfere.
It's a bit annoying that these two unrelated differences come in the same package, and that you can't get an unscoped enumeration with no implicit conversion, but generally both changes are Good Things and enum class is a good default practice in C++11.
EDIT: A scoped enumeration is defined like this:
enum class duck { huey, dewey, louie };
and must be used with the scope resolution operator :: like this:
duck culprit = duck::huey; // or "auto culprit" to avoid redundancy
Note that the :: operator also works with C++03 unscoped enumerations, so the second line above would work even if the first was missing class.
This might be excessive detail, but class does not go into the elaborated-type-specifier if forward declaring the enumerated type, as in
void quack( enum duck whom ); // not "enum class"
However, there is a construct new in C++11, the opaque-enum-declaration, which does include the class keyword and defines a complete type.
enum duck; // duck is declared as incomplete type
enum class duck; // duck is now complete type; underlying type defaults to int
The keyword struct can be substituted for class with no semantic difference.
You can explicitly specify the storage type when the data size is important (packing it in a struct perhaps).
The enumeration values are scoped within the name of the enum only; before c++11 they leaked into the enclosing scope.
I seem to recall the conversion rules were also changed somewhat...
In relation to point one 1, the storage size of enums would change before C++11 depending on the largest value assigned to an enumeration. Usually it doesn't matter so much, but when it does you have to resort to ugly hacks to force the size.
As for point 3, in C++11 enums are not implicitly convertible or comparable to ints or other enum types: useful for avoiding function overloading headaches and other implicit conversion gotchas.
Personnally I have used it in a tcp based messaging protocol: many of the fields were enum values that I needed to encode inside one byte only, so as to respect the messaging interface..
All my enums were simply defined this way:
enum class EnumFieldA : unsigned char { eValProperty1, eValProperty2};
enum class EnumFieldB : unsigned char { eValProperty1, eValProperty2, eValProperty3};
enum class EnumFieldC : unsigned char { eValProperty1, eValProperty2, eValProperty3, eValProperty4};
...
there are also plenty of thorough answers in this SO question.
At first I was confused by your question, but I think you want to know the difference between c++ enum and that in c++11. As best as I can understand, in the later, you have strongly typed enums which allows you to scope your them. I think this explains it well. CHEERS

C++ For what types can the parameter type name be the same as the parameter name with a type specifier?

This question is going to take a bit of explination, sorry. I am fixing an oversight in doxygen parsing some C++ code and I have come across an unusual corner case that doxygen doesn't account for. I have a fix but I want to make it more general so I need some explanation.
To illustrate the case where doxygen is failing I am going to define a contrived example involving The Simpsons (because that seems to be popular for these types of questions). Let's say that we have the following enum:
enum simpson { HOMER, MARGE, BART, LISA, MAGGIE };
Now we want to pass the enum value into a method (of the Simpsons class naturally) that looks like this:
const char* voicedBy(simpson simpson)
{
switch (simpson) {
case HOMER:
return "Dan Castellaneta";
case MARGE:
return "Julie Kavner";
case BART:
return "Nancy Cartwright";
case LISA:
return "Yeardley Smith";
case MAGGIE:
return "*suck* *suck*";
}
}
Unfortunately this produces a compiler error because the enum type 'simpson' is not allowed to be the same as the parameter name 'simpson' (Unlike in, say, C#). But, C++ has an answer to this. You put the enum keyword in front of the type name like this:
const char* voicedBy(enum simpson simpson)
and the code will now compile and run. Unfortunately doxygen doesn't account for this case and so it treats the entire string "enum simpson simpson" as a parameter type with no parameter name. I have come up with some code to fix doxygen in the case of an enum like above.
My question is, what other types is this kind of trick valid for? struct?, union?, typedef?, others? And for that matter, does the 'type specifier for method parameter with same name as parameter name' concept have a name so that I can get some more details on it?
What compiler and version are you using?
void foo( simpson simpson ) {}
No enum present, that is, you don't need to use an elaborated type specifier in this context, and it compiles perfectly in gcc 4.2 and 4.6. The problem is that inside the function, the argument name hides* the type, and if you want to declare a new variable with that type inside that scope you will need the elaborated type specifier, but in the function signature it is parsed left to right, and that means that the first simpson is the enum and at that time there is no collision. The second simpson introduces a local name, and from there on, simpson refers to the parameter and not the type.
void relationship( /*enum*/ simpson simpson, enum simpson other = HOMER );
// ^^^^ optional ^^^^ required
{
enum simpson yet_another = simpson;
// ^^^^ required ^^^^^^^ first argument!
}
The same type of name hiding can happen if you define a function with the same name as the type you want:
void simpson();
void voicedBy( enum simpson s );
// ^^^^ required
Note that if you add a typedef the things change a little in this last case: there will be a name clash between the typedef-ed name and the function name (or a variable name in the same scope).
* Here hides is not used in the sense of a variable in one scope hiding a variable with the same name in an outer scope. In C++, as in C, there are two identifier spaces, one for user defined types, and another for mostly everything else including typedef-ed type aliases. Lookup in C++ is performed from the inner scope to the outer scope, and in each scope the global identifier space is searched, if the identifier is not found, then the user defined types identifier space is searched for the same identifier. This last step is not performed in C, where elaborated type specifiers are required always. Only if that also fails, the compiler will move to the next scope.
In C, the canonical name of a struct, union, or enum includes that prefix:
struct Point {
int x, y;
};
enum Type {
FIRST, SECOND, THIRD
};
struct Point p;
enum Type t;
Which is the source of the idiom of creating a typedef name with the prefix removed:
typedef struct Point {
int x, y;
} Point;
typedef enum Type {
FIRST, SECOND, THIRD
} Type;
struct Point p;
enum Type t;
Point p;
Type t;
C++ has this as well, with the same behaviour also given to class, and analogous behaviour given to template and typename in templates. However, it also removes the requirement of including the prefix except in ambiguous cases.
I didn't think this concept had a name, but I stand corrected: it's an elaborated type specifier. A suitable workaround for this may be to place the Doxygen comments on the declaration rather than the definition.
What you did there is the same thing C coders do all day - prefixing their user defined types with the appropriate keyword. The same works for struct, class, union, in typedefs, variable declarations, anywhere basically.
struct/class/union also. In the Standard, "elaborated-type-specifier"s, consisting of "class-key identifier", see 3.4.4-1. (BTW - if a switch case returns, it has no need to break.)

Mixing class and struct

I'm well aware of the difference between class and struct, however I'm struggling to authoritatively say if this is well defined:
// declare foo (struct)
struct foo;
// define foo (class)
class foo {
};
// instance of foo, claiming to be a struct again! Well defined?
struct foo bar;
// mixing class and struct like this upsets at least one compiler (names are mangled differently)
const foo& test() {
return bar;
}
int main() {
test();
return 0;
}
If this is undefined behaviour can someone point me in the direction of an authoritative (i.e. chapter and verse from ISO) reference?
The compiler with problems handling this (Carbide 2.7) is relatively old and all the other compilers I've tried it on are perfectly happy with this, but clearly that doesn't prove anything.
My intuition was this ought to be undefined behaviour but I can't find anything to confirm this and I'm surprised that none of the GCC versions or Comeau so much as warned about it.
It looks to me like it's defined behavior. In particular, §9.1/2 says:
A declaration consisting solely of class-key identifier ; is either a redeclaration of the
name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name into the current scope.
The standard distinguishes between using class, struct or union when defining a class, but here, talking about a declaration, no such distinction is made -- using one class-key is equivalent to any other.
Technically the code is ok, according to the language standard. However, as at least one of the most popular compilers issues a warning for this, it doesn't work in practice.
"In theory, there is no difference between theory and practice. In pratice, there is."
From Warning C4099: type name first seen using 'class' now seen using 'struct' (MS VS 2k8) it appears that at least some compilers mangle differently depending on keyword used, so best not to rely on it even if it's technically allowed (of which I can't find a confirming reference).
In C++, a struct is a class. Specifically:
A structure is a class defined with
the class-key struct. (ISO/IEC FDIS
14882:1998(E) 9-4)
This implies that your class, which was not defined with struct, is definitely not a struct. Therefore, your forward declaration with the struct class-key is erroneous. I'm not aware of any part of the specification that allows a forward declaration to use a class-key that is clearly wrong. I'm sure that the lenient compilers in question treat structs and classes equally and are glossing over the incorrect declaration. An error may not be required from the compiler in this scenario, but neither should it be unexpected.
I have no idea whether or not this is undefined (or any of the other categories of not-strictly-conforming) per the C standard, but I do know that if you have two translation units that don't agree on whether a type 'foo' is declared as a 'class' or a 'struct', like so:
TU 1
struct foo;
void f(foo&) { ... }
TU 2
class foo { ... };
void f(foo&);
void g()
{
foo x;
f(x);
}
then, at least some compilers (notably MSVC++) will mangle the name of f differently in each translation unit, so the definition of f in TU 1 does not satisfy the reference to f in TU 2 and you get a link error. This comes up in real life when you have a header A.h that defines class A and needs to refer to classes B, C, and D but a forward declaration of them suffices (so it, quite sensibly, does not include B.h etc) -- you better use the same keyword for those forward declarations that the actual definitions do!
MSVC10 throws a warning, and the warning page states that the type given in the definition will be used.
http://msdn.microsoft.com/en-us/library/695x5bes.aspx