Re: enums that are really just sets of constants

2017-04-19 Thread Dr. Diether Knof
Hello,

I welcome the change to enum classes. I have made this transition recently in 
my project and want to share my experience:

A conversion to bool from enum class is possible via
  bool operator!(ResponseType i) { return (i != ResponesType::NONE); }
  ResponseType i = f();
  if (!i) ;
  if (!!i) ; // it is not possible to use 'if (i)'

A comparison is also possible:
  bool operator<(BuiltinIconSize lhs, BuiltinIconSize rhs);

For numbers, which are |ed (like CalendarDisplayOptions) your second suggestion 
looks promising. But it will be a hack to get
  void Calendar::set_display_options(Calendar::DisplayOptions flags);
to accept
  calendar.set_display_options(Calendar::DisplayOptions::SHOW_HEADING | 
Calendar::DisplayOptions::SHOW_DAY_NAMES); 

And it would be good to further disallow
  Calendar::DisplayOptions::SHOW_HEADING | UIManager::ItemType::POPUP


Diether


pgpE5lnw1EyzH.pgp
Description: Digitale Signatur von OpenPGP
___
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list


Re: enums that are really just sets of constants

2017-04-19 Thread Jonathan Wakely
On 19 April 2017 at 11:51, Kjell Ahlstedt wrote:
> Den 2017-04-19 kl. 12:24, skrev Murray Cumming:
>
> On Wed, 2017-04-19 at 10:30 +0100, Jonathan Wakely wrote:
>
> 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.
>
> Is it possible to define a namespace within a class?

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


Re: enums that are really just sets of constants

2017-04-19 Thread Murray Cumming
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


Re: enums that are really just sets of constants

2017-04-19 Thread Jonathan Wakely
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?

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

> 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).

> 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. 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? 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.
___
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list


Re: enums that are really just sets of constants

2017-04-19 Thread Daniel Boles
On 19 April 2017 at 09:37, Murray Cumming  wrote:

> 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. 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:
> 2. Use constexpr int constants inside a class:
>


FWIW, I try to avoid using classes where I don't actually need them (though
of course all bets are off where templates come into play), so I would also
suggest putting such constants in a namespace, instead of a class. I'm not
sure how popular that viewpoint is, but fwiw, a quick search did find some
other people on Stack Overflow favouring it.
___
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list


enums that are really just sets of constants

2017-04-19 Thread Murray Cumming
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. 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,
...
  };
};

But shouldn't we just avoid old-style enums completely?


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?

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

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