C2 forum

General Category => Ideas => Topic started by: bas on July 20, 2015, 04:43:25 PM

Title: Enum classes
Post by: bas on July 20, 2015, 04:43:25 PM
Recently C++11 introduced the concept of enum classes. This puts the enum constants
in their own enum's namespace. So:

Code: [Select]
enum class State {
   START,
   MIDDLE,
   END
};

This allows the compiler to detect clashes between different enums and some other tricks. A second advantage
is avoiding name clashes between the MIDDLE of one enum type with MIDDLE of the second enum type.

In C2 there are already modules to avoid clashes, but currently the enum constants (like START, MIDDLE, etc)
end up in that modules namespace. I'm toying with the idea to always put enum constants in their own namespace.
The declaration will still look exactly the same, but the usage now uses an enum namespace, like

Code: [Select]
module test;

type State enum int32 {
  Start,
  Middle,
  End
}

func void foo() {
   State s1 = Start;               // current situation (full: test.Start)
   State s2 = State::Start;     // option 1 (full: test.State::Start)
   State s3 = State.Start;      // option 2 (full: test.State.Start)

}

Note that the module member operator is already a dot (.). I prefer test.State::Start over
test.State.Start, since it distinguishes the enum namespace and a.b is always either a module
or struct member. Once again I look for the experience and wisdom of the forum members :)
Title: Re: Enum classes
Post by: chqrlie on August 30, 2015, 11:28:02 AM
This is probably just a matter of taste, but the syntax with the :: class or namespace specifier does not appeal to me at all.

It seems also overkill to make enum constants separate by default.  It is an unnecessary departure from C.  The module namespace already isolates the names from other modules.

Whether a single level of module name spacing is sufficient is another matter.  I'm considering porting qemacs to C2 as a full scale sample project, and it would make sense the have separate modules for the various functional parts of this moderate size project (50K slcc).  Yet all these modules should be submodules of a more general qemacs "package".

In any case, please avoid the double colon ( :: ) and the angle brackets (< >), the C++/Java look and feel is not appealing.
Title: Re: Enum classes
Post by: bas on August 30, 2015, 11:55:47 AM
Let's discuss the enums first. One of my goals is to make the language as unambiguous as possible.
So code like

Code: [Select]
a.b
can be 2 things:

I sometimes find it handy to isolate enum values from a regular 'namespace', especially
if there are multiple enum types in the same 'namespace'. If we would add this feature,
using the dot operator would make things more ambiguous (like a.b.c), so therefore I
tried the :: operator. I agree that this somewhat breaks the uniformity of the syntax...

As a sidenote, so does the current 'cast' operator, but the old C-style cast simply wasn't
very parse-able..

The second issue you mention, whether a single level of module name spacing is sufficient
is indeed another matter. I think there is a different post discussing that. There we concluded that
having a single level is already better than none and that adding more would only add more
complexity without too much gain. You can of course use something like

Code: [Select]
module qemacs_foobar;

and then import it like
Code: [Select]
import qemacs_foobar as foobar;
Porting a larger project to C2 would be a *very* nice way to see how some features fit!
Title: Re: Enum classes
Post by: DerSaidin on August 30, 2015, 02:49:27 PM
Hello,

I think the main advantage of enum classes in C++11 is better type safety. You can't just use enum values like integers anymore.

With more knowledge of the types, do you need the enum namespace explicit in the code to be unambiguous?
Does it actually remove any ambiguity?

Code: [Select]
State s2 = SomethingOtherThanState::Start;  // won't ever work anyway, it has to be in Start::

Is there any case were you don't know the type of the LHS, and having the enum type as part of the RHS would be necessary?

Although personally I wouldn't mind being overly explicit, even if unnecessary, and requiring the enum value to specifying the namespace  :)
Title: Re: Enum classes
Post by: chqrlie on August 30, 2015, 10:37:14 PM
You both have valid points.  I don't have a definite position on this issue (aside from the syntax preferences).  I am a pragmatic programmer: I'd rather build an opinion from first hand experience with a real life project. Hopefully before the end of this year!
Title: Re: Enum classes
Post by: kyle on December 22, 2016, 12:36:18 AM
Sorry for the late reply.  I lost my links to C2 during a particularly busy period and it dropped off my mental horizon (which is admittedly rather small).

The type features of C++ new enums are really nice.   I would strongly suggest something that keeps that kind of distinction.

As to modules.   C has (sort of) two levels of function: one for static (translation unit) and one for extern (whole program).   This has been sufficient for a long, long time.   I'd keep just one level of module.

I haven't caught up yet with all the other work on the forum so please excuse any duplication!
Title: Re: Enum classes
Post by: bas on January 02, 2017, 08:30:36 PM
The big advantage of explicit enum types would be to catch mistakes like:
Code: [Select]
type Temperature enum int8 {
  Low,
  High,
}

type State enum int8 {
  Begin,
  End,
}

State state = High;  // <- wrong enum constant

In languages where an enum is just an integer, the above would be perfectly fine. Currently the C2 compiler
catches these issues (but ATM doesn't give a nice diagnostic msg yet). So internally, enum constants have
the type of the enum (and not just int8). Maybe that's enough for now, since the only other advantage is being
able to have different enum types in the same module, with same enum constants (eg. both have a 'Middle')...
Title: Re: Enum classes
Post by: bas on January 04, 2017, 07:45:40 AM
Most modern C compilers will give a warning on this. In C2 this will just be an error and requires an
explicit cast to work..