enums that are really just sets of constants

classic Classic list List threaded Threaded
23 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

enums that are really just sets of constants

Murray Cumming-5
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
[hidden email]
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Daniel Boles

On 19 April 2017 at 09:37, Murray Cumming <[hidden email]> 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
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Jonathan Wakely
In reply to this post by Murray Cumming-5
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
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Murray Cumming-5
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
[hidden email]
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Kjell Ahlstedt-2
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?
class A {
public:
  namespace B {
    enum C { .... };
  }
  void f();
  ...
};
If we choose to put the enum or the set of named integer constants in a namespace, must we refrain from putting them inside a class, such as the Gtk::ResponseType enum within the Gtk::Dialog class?
But shouldn't we just avoid old-style enums completely?
Why? Both types still have uses in modern C++. Old doesn't mean bad.


_WRAP_GERROR still generates old-style enums. We would not gain anything by changing that.

Kjell

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

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
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Dr. Diether Knof
In reply to this post by Murray Cumming-5
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

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list

attachment0 (220 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Dr. Diether Knof
Hello,

for the integer wraps used for flags I have a third proposition, a working example is attached:
* "enum class DisplayOption" for the individual flags
* "class DisplayOptions" with an implicit converter DisplayOption -> DisplayOptions
So we get an enum for the single options and avoid the old enum-style.

Diether


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list

test_enum.cpp (1K) Download Attachment
attachment1 (220 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Jonathan Wakely
On 22 April 2017 at 05:57, Dr. Diether Knof wrote:
> Hello,
>
> for the integer wraps used for flags I have a third proposition, a working example is attached:
> * "enum class DisplayOption" for the individual flags
> * "class DisplayOptions" with an implicit converter DisplayOption -> DisplayOptions
> So we get an enum for the single options and avoid the old enum-style.

Why not have the constants declared inside the class, so you only have
one name to remember, not DisplayOption and DisplayOptions?

You can overload operator| and operator& for enums, so the only
benefit to this seems to be the implicit conversion to bool (why not
explciit?)
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Kjell Ahlstedt-2
In reply to this post by Murray Cumming-5
Den 2017-04-19 kl. 10:37, skrev 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:
But shouldn't we just avoid old-style enums completely?


2. Use constexpr int constants inside a class:
But shouldn't we use some kind of enum to group the values together?

Have we decided what to do? According to other posts in this thread there are 4 possibilities:

1. Old-style enums inside a class.
2. constexpr int constants inside a class.
3. Old-style enums inside a namespace.
4. constexpr int constants inside a namespace.

A namespace can't be declared inside a class. We can't declare Gtk::ResponseType inside Gtk::Dialog, if ResponseType is a namespace.

Jonathan Wakeley has pointed out that a class has greater overhead than a namespace. The overhead can be kept to a minimum, however. These classes won't have virtual methods, so they won't have RTTI. They won't need a public constructor. It can be made illegal to create instances of them. They can be declared final to stop people from deriving from them.

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Daniel Boles
On 4 May 2017 at 15:24, Kjell Ahlstedt <[hidden email]> wrote:
Have we decided what to do? According to other posts in this thread there are 4 possibilities:

1. Old-style enums inside a class.
2. constexpr int constants inside a class.
3. Old-style enums inside a namespace.
4. constexpr int constants inside a namespace.

A namespace can't be declared inside a class. We can't declare Gtk::ResponseType inside Gtk::Dialog, if ResponseType is a namespace.

Jonathan Wakeley has pointed out that a class has greater overhead than a namespace. The overhead can be kept to a minimum, however. These classes won't have virtual methods, so they won't have RTTI. They won't need a public constructor. It can be made illegal to create instances of them. They can be declared final to stop people from deriving from them.


So it seems that the only option is to continue using C-style enums within classes, e.g. class Dialog { enum ResponseType{} } as present.. As someone already mentioned, I see no problem with this: such an enum is not inherently bad in itself; it's only bad if chosen in o s case where another solution (enum class, constexpr, etc.) is an available and more appropriate option. As that does not apply, the C-style enum should continue to serve this purpose well.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Daniel Boles
On 6 May 2017 at 18:23, Nicklas Karlsson <[hidden email]> wrote:
I think C-style enums lack possibility to specify how many bits should be used for storage which is useful then decoding from some kind of raw data.

No, the underlying type can also be specified for plain enums too. Try it: enum MyPlainEnum: unsigned char

And there's my next point: it's hard to think of a case where this is really useful for 'decoding from raw data', given the very limited allowances that C++ makes for type-punning and other shenanigans. To me it's only useful for conveying numerical semantics and saving space in class layouts, not much else.



 

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Murray Cumming-5
In reply to this post by Daniel Boles
On Sat, 2017-05-06 at 18:08 +0100, Daniel Boles wrote:
> So it seems that the only option is to continue using C-style enums
> within classes, e.g. class Dialog { enum ResponseType{} } as
> present.. As someone already mentioned, I see no problem with this:
> such an enum is not inherently bad in itself; it's only bad if chosen
> in o s case where another solution (enum class, constexpr, etc.) is
> an available and more appropriate option. As that does not apply, the
> C-style enum should continue to serve this purpose well.

The old style-enum won't let us change this, in gtkmm 3,
Gtk::RESPONSE_OK
into this, in gtkmm 4:
Gtk::Dialog::Response::OK
without also polluting the API with this
Gtk::Dialog::OK

Using an old-style enum would let us have this:
Gtk::Dialog::RESPONSE_OK,
(and Gtk::Dialog::Response::RESPONSE_OK)
which is still an improvement, but not quite as nice.

--
Murray Cumming
[hidden email]
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Jonathan Wakely
On 6 May 2017 at 21:00, Murray Cumming <[hidden email]> wrote:

> On Sat, 2017-05-06 at 18:08 +0100, Daniel Boles wrote:
>> So it seems that the only option is to continue using C-style enums
>> within classes, e.g. class Dialog { enum ResponseType{} } as
>> present.. As someone already mentioned, I see no problem with this:
>> such an enum is not inherently bad in itself; it's only bad if chosen
>> in o s case where another solution (enum class, constexpr, etc.) is
>> an available and more appropriate option. As that does not apply, the
>> C-style enum should continue to serve this purpose well.
>
> The old style-enum won't let us change this, in gtkmm 3,
> Gtk::RESPONSE_OK
> into this, in gtkmm 4:
> Gtk::Dialog::Response::OK
> without also polluting the API with this
> Gtk::Dialog::OK
>
> Using an old-style enum would let us have this:
> Gtk::Dialog::RESPONSE_OK,
> (and Gtk::Dialog::Response::RESPONSE_OK)
> which is still an improvement, but not quite as nice.

Strictly speaking, an old-style enum *and* a scope would allow that.

namespace Gtk {
  struct Dialog {
    struct Response {
      enum ResponseEnum { OK };
    };
  };
}

That would give you the implicit conversions of old-style enums, but
still give scoped names. That might not be useful, I'm just saying
it's possible.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Kjell Ahlstedt-2
Den 2017-05-06 kl. 23:09, skrev Jonathan Wakely:
On 6 May 2017 at 21:00, Murray Cumming [hidden email] wrote:
The old style-enum won't let us change this, in gtkmm 3,
Gtk::RESPONSE_OK
into this, in gtkmm 4:
Gtk::Dialog::Response::OK
without also polluting the API with this
Gtk::Dialog::OK

Using an old-style enum would let us have this:
Gtk::Dialog::RESPONSE_OK,
(and Gtk::Dialog::Response::RESPONSE_OK)
which is still an improvement, but not quite as nice.
Strictly speaking, an old-style enum *and* a scope would allow that.

namespace Gtk {
  struct Dialog {
    struct Response {
      enum ResponseEnum { OK };
    };
  };
}

That would give you the implicit conversions of old-style enums, but
still give scoped names. That might not be useful, I'm just saying
it's possible.
_______________________________________________

That might very well be useful. A minor drawback is that we would have both Gtk::Dialog::Response::OK (wanted) and Gtk::Dialog::Response::ResponseEnum::OK (unwanted). With an unnamed old-style enum there would be only Gtk::Dialog::Response::OK.

namespace Gtk {
  class Dialog : public ... {
  public:
    struct Response {
      enum { OK };
    };
  };
}

An unnamed enum entails some restrictions, as discussed in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c34, but that's probably not important for the very few enums in gtkmm and other mm-modules where we want implicit conversion to int.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Jonathan Wakely
On 7 May 2017 at 15:10, Kjell Ahlstedt <[hidden email]> wrote:

> Den 2017-05-06 kl. 23:09, skrev Jonathan Wakely:
>
> On 6 May 2017 at 21:00, Murray Cumming <[hidden email]> wrote:
>
> The old style-enum won't let us change this, in gtkmm 3,
>
> Gtk::RESPONSE_OK
> into this, in gtkmm 4:
> Gtk::Dialog::Response::OK
> without also polluting the API with this
> Gtk::Dialog::OK
>
> Using an old-style enum would let us have this:
> Gtk::Dialog::RESPONSE_OK,
> (and Gtk::Dialog::Response::RESPONSE_OK)
> which is still an improvement, but not quite as nice.
>
> Strictly speaking, an old-style enum *and* a scope would allow that.
>
> namespace Gtk {
>   struct Dialog {
>     struct Response {
>       enum ResponseEnum { OK };
>     };
>   };
> }
>
> That would give you the implicit conversions of old-style enums, but
> still give scoped names. That might not be useful, I'm just saying
> it's possible.
> _______________________________________________
>
> That might very well be useful. A minor drawback is that we would have both
> Gtk::Dialog::Response::OK (wanted) and
> Gtk::Dialog::Response::ResponseEnum::OK (unwanted). With an unnamed
> old-style enum there would be only Gtk::Dialog::Response::OK.
>
> namespace Gtk {
>   class Dialog : public ... {
>   public:
>     struct Response {
>       enum { OK };
>     };
>   };
> }
>
> An unnamed enum entails some restrictions, as discussed in
> https://bugzilla.gnome.org/show_bug.cgi?id=86864#c34, but that's probably
> not important for the very few enums in gtkmm and other mm-modules where we
> want implicit conversion to int.

Personally I find the downsides of unnamed enumerations types (can't
overload on the type, don't have a name to refer to the constants even
though they are allegedly related) are much worse than the fact there
are two ways to refer to the enumerations. I've never seen problems
arising from the fact that you could also write
Gtk::Dialog::Dialog::Dialog::Dialog::Response::OK (because of the
injected-class-name) so I don't see why the case you mentioned would
be a real problem.

If you're really worried about it:

namespace Gtk {
  class Dialog : public ... {
  public:
    struct Response {
      enum ResponseEnum { };
      static constexpr ResponseEnum OK = 0;
      static constexpr ResponseEnum ERR1 = 1;
      static constexpr ResponseEnum ERR2 = 2;
    };
  };
}

But I don't think that's an improvement.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Kjell Ahlstedt-2
Den 2017-05-08 kl. 20:49, skrev Jonathan Wakely:
On 7 May 2017 at 15:10, Kjell Ahlstedt [hidden email] wrote:
Den 2017-05-06 kl. 23:09, skrev Jonathan Wakely:

On 6 May 2017 at 21:00, Murray Cumming [hidden email] wrote:

The old style-enum won't let us change this, in gtkmm 3,

Gtk::RESPONSE_OK
into this, in gtkmm 4:
Gtk::Dialog::Response::OK
without also polluting the API with this
Gtk::Dialog::OK

Using an old-style enum would let us have this:
Gtk::Dialog::RESPONSE_OK,
(and Gtk::Dialog::Response::RESPONSE_OK)
which is still an improvement, but not quite as nice.

Strictly speaking, an old-style enum *and* a scope would allow that.

namespace Gtk {
  struct Dialog {
    struct Response {
      enum ResponseEnum { OK };
    };
  };
}

That would give you the implicit conversions of old-style enums, but
still give scoped names. That might not be useful, I'm just saying
it's possible.
_______________________________________________

That might very well be useful. A minor drawback is that we would have both
Gtk::Dialog::Response::OK (wanted) and
Gtk::Dialog::Response::ResponseEnum::OK (unwanted). With an unnamed
old-style enum there would be only Gtk::Dialog::Response::OK.

namespace Gtk {
  class Dialog : public ... {
  public:
    struct Response {
      enum { OK };
    };
  };
}

An unnamed enum entails some restrictions, as discussed in
https://bugzilla.gnome.org/show_bug.cgi?id=86864#c34, but that's probably
not important for the very few enums in gtkmm and other mm-modules where we
want implicit conversion to int.
Personally I find the downsides of unnamed enumerations types (can't
overload on the type, don't have a name to refer to the constants even
though they are allegedly related) are much worse than the fact there
are two ways to refer to the enumerations. I've never seen problems
arising from the fact that you could also write
Gtk::Dialog::Dialog::Dialog::Dialog::Response::OK (because of the
injected-class-name) so I don't see why the case you mentioned would
be a real problem.

If you're really worried about it:

namespace Gtk {
  class Dialog : public ... {
  public:
    struct Response {
      enum ResponseEnum { };
      static constexpr ResponseEnum OK = 0;
      static constexpr ResponseEnum ERR1 = 1;
      static constexpr ResponseEnum ERR2 = 2;
    };
  };
}

But I don't think that's an improvement.
Yet another suggestion in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Kjell Ahlstedt-2
Den 2017-05-13 kl. 10:04, skrev Kjell Ahlstedt:
Yet another suggestion in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43

Can we decide what to do with the few enums that we want to be implicitly convertible to int? My suggestion in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43 is

  class ResponseType_Enum final
  {
  public:
    enum ResponseType
    {
      NONE = -1,
      REJECT = -2,
      ACCEPT = -3,
      ...
    };
    ResponseType_Enum() = delete;
  };
  using ResponseType = ResponseType_Enum::ResponseType;

I tried to make a mixture of a plain (old-style) enum and an enum class. It shall be implicitly convertible to int, and its enumerators shall be scoped. In other respects it shall be possible to use it as if it's an enum, e.g.

  ResponseType r = ResponseType::REJECT;
  int i = r;
but not
  r = REJECT;
  i = REJECT;
and preferably not
  r = i;

Daniel has remarked that _Enum is not a good suffix for a class name. I agree. Can you think of a better suffix? I don't want to call the class ResponseType. That would clash with using ResponseType = .... If it shall be possible to use ResponseType as if it's the name of an enum, it must be the name of an enum or an alias for a name of an enum. Or are there other possibilities that are not too complicated?


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Ian Arkver
On 23/05/17 08:51, Kjell Ahlstedt wrote:

> Den 2017-05-13 kl. 10:04, skrev Kjell Ahlstedt:
>> Yet another suggestion in
>> https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43
>>
> Can we decide what to do with the few enums that we want to be
> implicitly convertible to int? My suggestion in
> https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43 is
>
>    class ResponseType_Enum final
>    {
>    public:
>      enum ResponseType
>      {
>        NONE = -1,
>        REJECT = -2,
>        ACCEPT = -3,
>        ...
>      };
>      ResponseType_Enum() = delete;
>    };
>    using ResponseType = ResponseType_Enum::ResponseType;
>
> I tried to make a mixture of a plain (old-style) enum and an enum class.
> It shall be implicitly convertible to int, and its enumerators shall be
> scoped. In other respects it shall be possible to use it as if it's an
> enum, e.g.
>
>    ResponseType r = ResponseType::REJECT;
>    int i = r;
> but not
>    r = REJECT;
>    i = REJECT;
> and preferably not
>    r = i;
>
> Daniel has remarked that _Enum is not a good suffix for a class name. I
> agree. Can you think of a better suffix? I don't want to call the class
> /ResponseType/. That would clash with /using ResponseType = .../. If it
> shall be possible to use /ResponseType/ as if it's the name of an enum,
> it must be the name of an enum or an alias for a name of an enum. Or are
> there other possibilities that are not too complicated?

ResponseType_Values maybe?

Regards,
Ian
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: enums that are really just sets of constants

Jonathan Wakely
In reply to this post by Kjell Ahlstedt-2


On 23 May 2017 at 08:51, Kjell Ahlstedt <[hidden email]> wrote:
Den 2017-05-13 kl. 10:04, skrev Kjell Ahlstedt:
Yet another suggestion in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43

Can we decide what to do with the few enums that we want to be implicitly convertible to int? My suggestion in https://bugzilla.gnome.org/show_bug.cgi?id=86864#c43 is

  class ResponseType_Enum final
  {
  public:
    enum ResponseType
    {
      NONE = -1,
      REJECT = -2,
      ACCEPT = -3,
      ...
    };
    ResponseType_Enum() = delete;
  };
  using ResponseType = ResponseType_Enum::ResponseType;

I tried to make a mixture of a plain (old-style) enum and an enum class. It shall be implicitly convertible to int, and its enumerators shall be scoped. In other respects it shall be possible to use it as if it's an enum, e.g.

  ResponseType r = ResponseType::REJECT;
  int i = r;
but not
  r = REJECT;
  i = REJECT;
and preferably not
  r = i;

Daniel has remarked that _Enum is not a good suffix for a class name. I agree. Can you think of a better suffix? I don't want to call the class ResponseType. That would clash with using ResponseType = .... If it shall be possible to use ResponseType as if it's the name of an enum, it must be the name of an enum or an alias for a name of an enum. Or are there other possibilities that are not too complicated?

Would Response::Type work?

struct Response final
{
  enum Type { ... };
  Response() = delete;
};

void foo(Response::Type = Response::REJECT); 




_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
12
Loading...