[Development] API style guide: scoped enum or not?

Tor Arne Vestbø Tor.arne.Vestbo at qt.io
Wed May 3 19:38:00 CEST 2023



On 3 May 2023, at 18:40, Giuseppe D'Angelo via Development <development at qt-project.org> wrote:

Il 02/05/23 10:58, Volker Hilsheimer via Development ha scritto:
During the header review, but also in API discussions leading up to it, we had a few cases where it would have helped if we had clearer guidelines about when to use scoped enums, and when not.
Scoped enums have some clear technical advantages (such as better type safety, thanks to no implicit conversion to int). And they sometimes result in better APIs when enum values don’t have to repeat the enum’s name in order to be clear.

Should we vote on this? To me it's a no brainer: any new enumeration added to Qt shall be an enum class.

But sometimes it’s also creating too much verbosity to use a scoped enum (ie. Qt::Orientation::Horizontal would perhaps not be an improvement).

I wouldn't consider this tiny bit of extra verbosity a huge impediment. Note that Qt::Horizontal is violating the API naming guidelines. It should've been called Qt::HorizontalOrientation. How is that now better than Qt::Orientation::Horizontal?

No, Qt::Horizontal isn't "unambiguous" so it can't be non-qualified. Does it refer to what? Text alignment? Text direction? Layout direction? (Hint: none of these.)

These are all straw men.

I’ll quote directly from https://wiki.qt.io/API_Design_Principles#Naming_Enum_Types_and_Values
Naming Enum Types and Values

The guiding principle is to avoid name clashes between enum values and to ensure readability code with reasonable verbosity.

Enums in Qt/global namespace

New enums in the Qt namespace should always use scoped/strong enumerators by default. The scoping/strong typing ensures that there is no conflict if the same enum value name is used multiple times:

 namespace Qt
 {
   enum class Color {
     Blue,
     Orange,
     Yellow
   };

   enum class FavoriteColor {
     Yellow,
     Orange
   };
 }

 Color yellow = Qt::Color::Yellow;
 FavoriteColor yellow2 = Qt::FavoriteColor::Yellow;
 yellow2 = Qt::Orange; // error


When using scoped enums additional naming rules (repeating of enum type name inside enum value name) for are not necessary.

Enums in classes

Enums inside a class do not have the same problem of names clashing, as they are already namespaced within the class.

There are still reasons to prefer scoped enums inside classes, but this should be decided on a case by case basis.

If the enum values have a clear relation to the parent class, prefer un-scoped enums:

 class TouchPoint
 {
   enum State {
        Pressed,
        Held,
        Released
   };
};

// The context is clear when used outside the class
if (point.state() == TouchPoint::Pressed)
   ...

// As well as when used inside it
if (state() == Pressed)
   ...


Using scoped enums in this case would add redundant line noise:

if (point.state() == TouchPoint::State::Pressed)
   ...
if (state() == State::Pressed)
   ...


Note that the context where the enum is used, such as the name of the getter that returns the enum value, might be enough information to make a scoped enum redundant.

If the enum values do not have a natural relation to the class name, prefer scoped enums, e.g.:

 class QSslCertificate
 {
   enum class PatternSyntax {
        RegularExpression,
        Wildcard,
        FixedString
   };
};

if (syntax == PatternSyntax::Wildcard)
  ...


Another option to avoid the name clash instead of scoped/strong enums is to embedded the enum type name into each enum value. This method was extensively used in Qt 4 before scoped/strong enums were available.

 class Widget
 {
      enum Corner {
           TopLeftCorner,
           BottomRightCorner,
            …
      };
 };

 tabWidget->setCornerWidget(widget, Widget::TopLeftCorner);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20230503/3f95decb/attachment-0001.htm>


More information about the Development mailing list