On Wed, 2017-04-19 at 10:30 +0100, Jonathan Wakely wrote:
> On 19 April 2017 at 09:37, Murray Cumming wrote:
> > In the ABI-breaking versions of glibmm and gtkmm, we have recently
> > changed the enums to be C++11 "enum class"s. This is generally a
> > welcome improvement.
> > - Their values are, for instance, Things::ONE, rather than
> > THINGS_ONE.
> > - Their values do not convert implicitly to other types such as int
> > or
> > bool, helping the compiler to find some programmer mistakes.
> > 
> > We are also gradually moving the enums inside classes when they are
> > typically only used with that class.
> > 
> > However, some of the C enums that we wrap are actually meant to be
> > integer constants, so it seems that we cannot and should not use
> > "enum
> > class" for these.
> 
> How are they used? Are they compared to integers? Are they passed to
> gtk APIs that expect integers?

Both.

> You can use scoped enums anyway, but you'd need an explicit cast to
> an
> integer, so it might not be appropriate.

Yes, that's what we are doing right now. It's a bit ugly.

> > So I wonder what is the most "modern C++" way to do
> > this while keeping the new-style syntax. Here are two
> > possibilities:
> > 
> > 1. Use old-style enums inside a class:
> > 
> > class ResponseType {
> > public:
> >   enum Enum {
> >     NONE = -1,
> >     REJECT = -2,
> >     ACCEPT = -3,
> >     ...
> >   };
> > };
> 
> You can also use a namespace to give them their own scope, which has
> less overhead than a class type (no RTTI for the class, no way for
> users to create instances of the class type, or pointers to it, which
> would have no purpose if it's just being used to create a new scope
> for the enumerators).

Good point.

I'm leaning towards this at the moment.

> > But shouldn't we just avoid old-style enums completely?
> 
> Why? Both types still have uses in modern C++. Old doesn't mean bad.
> 
> N.B. since C++11 you can use the enumeration type's name as a
> qualification even for unscoped (i.e. old-style, non-class) enums:
> 
> enum E { Foo, Bar, Baz };
> 
> auto e = E::Foo;
> 
> So you can use the new syntax even with old-style enums. The problem
> is that you're not *required* to do that, you can still just say Foo,
> so the names still leak into the surrounding scope.

OK. I wouldn't like that.

>  With a scoped
> (i.e. new-style, class) enum the qualification is required.
> 
> 
> > 2. Use constexpr int constants inside a class:
> > 
> > class ResponseType {
> > public:
> >   constexpr int NONE = -1;
> >   constexpr int
> > REJECT = -2;
> >   constexpr int ACCEPT = -3;
> >   ...
> > };
> > 
> > But shouldn't we use some kind of enum to group the values
> > together?
> 
> Is their type actually important?

Not really. These are generally just ints.

>  i.e. are these different values of
> the same logical type? If yes, then using an enumeration makes sense.
> Otherwise just using an enumeration type to create an arbitrary group
> doesn't add any benefit.
> 
> The example above looks like these are different values for the same
> "thing" so giving them the same type makes sense to me. It allows
> overloading on that type, for example.
> 
> Aside: IMHO the shouty ALL_CAPS naming is not good style in C++, see
> https://accu.org/index.php/articles/1923 for my reasoning.

Yes, I saw that mentioned in the C++ Core Guidelines. I might need to
adapt my habits. But that's something to deal with later.

-- 
Murray Cumming
murr...@murrayc.com
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list

Reply via email to