Bug 168771 - Convert enum to enum class
Summary: Convert enum to enum class
Status: NEW
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
unspecified
Hardware: All All
: medium normal
Assignee: Not Assigned
URL:
Whiteboard: target:26.8.0
Keywords: difficultyBeginner, easyHack, skillCpp, topicCleanup
Depends on:
Blocks:
 
Reported: 2025-10-09 13:51 UTC by Hossein
Modified: 2026-01-13 17:08 UTC (History)
2 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hossein 2025-10-09 13:51:29 UTC
Description:
Since C++11 when enum class (also named scoped enum) is introduced, it is preferred to the plain enum which is inherited from C programming languages. The task here is to convert the old enums to enum class.

Rationale:
enum class has many benefits when compared to plain enum, as it provides better type safety among other things. Implicit conversion to integers, lack of ability to define the underlying data type and compatibility issues are some of the problems with plain enum that enum class solves.

Plain enums pollute namespace, and you have to pick names that are too long, and have to carry the context inside their names. For example: INETMSG_RFC822_BEGIN inside enum _ImplINetRFC822MessageHeaderState. With an enum class, it is simply written as HeaderState::BEGIN. When placed inside a file/class/namespace that makes it relevant, it is much easier to use: it is more readable, and causes no issues for other identifiers with possible similar names.,

commit 593f08303fef14243c8ee2ec4e1c1912628f59e8
convert enum _ImplINetRFC822MessageHeaderState to enum class

You can read more about that in:

Why is enum class considered safer to use than plain enum?
https://stackoverflow.com/questions/18335861/why-is-enum-class-considered-safer-to-use-than-plain-enum

Finding Instances:
You may find some of the instances with:

$ git grep -w enum *.cxx *.hxx|grep -v "enum class"

When you count it with 'wc -l', it shows something more than 2k instances. Please note that sometimes this conversion can reduce readability because of multiple "static_cast"s in return of no obvious gain. Then, let it be as is and pick another instance.

Examples Commits:
You can see some of the previous conversions here, which is around 1k changes:

$ git log --oneline -i -E --grep="convert enum|scoped enum"

This is a good, but lengthy example of such a conversion:

commit 9072c5c8551c0bc512865ab15b1054c78706f1f3
convert SbxFlagsBits to scoped enum

Implementation:
First of all, please choose good names for the new enum class and values. For example, you may convert APPLICATION_WINDOW_TITLE into Application::WindowTitle. Therefore, it is suggested not to use the old names as they were.

Converting enum to enum class is not always straightforward. You should try to understand the code using the enum, and then try to replace it with enum class. You may need to add extra state/values for situations where 0 or -1 or some default value was used. There are cases where a numerical value is used for different conflicting purposes, and then you have to do some sort of conflict resolution to separate those cases.

You may end up modifying more and more files, and a few static_casts where they are absolutely necessary because you are interpreting some integer value read from input. These are the places where you should check the values yourself in the code. You have to make sure that the numerical value is appropriate before casting it to the enum class.

If you want to do bitwise operations, you should use o3tl::typed_flags, for example:

template<> struct o3tl::typed_flags<FileViewFlags> : o3tl::is_typed_flags<FileViewFlags, 0x26> {}

Please note that 0x26 is the mask, and is calculated by applying OR over all possible values. All the values must be non-negative.
Comment 1 Stephan Bergmann 2025-10-10 06:05:22 UTC
(In reply to Hossein from comment #0)
> [...] lack
> of ability to define the underlying data type [...] are
> some of the problems with plain enum that enum class solves.

(that's not quite accurate, the underlying type can be explicitly specified also for unscoped enumerations, since C++ 11)
Comment 2 Hossein 2025-10-15 15:07:27 UTC
(In reply to Stephan Bergmann from comment #1)
> (In reply to Hossein from comment #0)
> > [...] lack
> > of ability to define the underlying data type [...] are
> > some of the problems with plain enum that enum class solves.
> (that's not quite accurate, the underlying type can be explicitly specified
> also for unscoped enumerations, since C++ 11)
Thanks Stephan for the above note. I clarify that before C++11 one could not specify the underlying type in enum, but since C++11 it is possible.

Beyond that, there are still many reasons to use 'enum class' instead of 'enum' in new enumerations.
Comment 3 Tomaz Vajngerl 2025-10-18 02:25:45 UTC
Note that instead of bit flags and messing with bitwise operators it's IMHO more straight forward to just declare a struct with 1-bit long booleans, which AFAIK should be pretty similar to bit flags but the compiler would do all the work.

For example:
enum class FileViewFlags
{
    None = 0x00,
    MultiSelection = 0x02,
    ShowType = 0x04,
    ShowNone = 0x20,
};

instead you could use 

struct FileViewFlags
{
   bool bMultiSelection : 1 = false;
   bool bShowType : 1 = false;
   bool bShowNone : 1 = false;
};

and... 

FileViewFlags eFlags = FileViewFlags::MultiSelection | FileViewFlags::ShowType;

if (eFlags & FileViewFlags::MultiSelection)
...

eFlags |= ShowType;

you can do:

FileViewFlags aFlags { .bMultiSelection = true, bShowType = true }

if (aFlags.bMultiSelection)
...

aFlags.bShowType = true;

if checking for "None" or in some cases "All" (or various other variations=, you can just add a isNone() or isAll() function. Then you check with:

if (eFlags & FileViewFlags::None)

vs.

if (aFlags.isNone())

or provide a static method FileViewFlags::None(), which is essentially just a shortcut for FileViewFlags(), FileViewFlags::All() would then be a short-cut for 

FileViewFlags aFlags { .bMultiSelection = true, bShowType = true, bShowNone = true }. 

then: 
if (aFlags == FileViewFlags::All()) 
and 
if (aFlags == FileViewFlags::None())

would work.

I think this is just less error prone than doing bitwise operations (especially when you want to set and unset bits it could become quite crappy)
Comment 4 Stephan Bergmann 2025-10-20 12:05:15 UTC
(In reply to Tomaz Vajngerl from comment #3)
> Note that instead of bit flags and messing with bitwise operators it's IMHO
> more straight forward to just declare a struct with 1-bit long booleans,

I think this would be non-portable at best, as:  "Allocation of bit-fields within a class object is implementation-defined." (C++20 [class.bit]/1)
Comment 5 Tomaz Vajngerl 2025-12-11 02:24:49 UTC
(In reply to Stephan Bergmann from comment #4)
> I think this would be non-portable at best, as:  "Allocation of bit-fields
> within a class object is implementation-defined." (C++20 [class.bit]/1)

Portable to what when large amount of uses of bit fields in the code base are not even in a place where this matters.
Comment 6 Stephan Bergmann 2025-12-11 10:48:27 UTC
(In reply to Tomaz Vajngerl from comment #5)
> (In reply to Stephan Bergmann from comment #4)
> > I think this would be non-portable at best, as:  "Allocation of bit-fields
> > within a class object is implementation-defined." (C++20 [class.bit]/1)
> 
> Portable to what when large amount of uses of bit fields in the code base
> are not even in a place where this matters.

(My assumption was that such enumerations were in general used in places where the data layout is mandated by some external protocol.  In places where that is not the case, it can indeed be beneficial to model the represented information in a more direct way.)
Comment 7 Commit Notification 2025-12-20 16:30:44 UTC
Simon Chenery committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/74d678191ac3fff6a3a1e9560763ea5870fabcf1

tdf#168771 Convert enum to enum class in methods1.cxx

It will be available in 26.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 8 Commit Notification 2025-12-28 16:19:32 UTC
Simon Chenery committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/53e65356c5385be6c917795e116049f10d63354b

tdf#168771 Convert enum to enum class in animimp.cxx

It will be available in 26.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 9 Commit Notification 2025-12-29 18:40:02 UTC
Pragat Pandya committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/89559c8bc7fe8afd9e8d99d6ef8bac5a57bf6e04

tdf#168771 Convert enum to enum class in xmlreader and xmlsecurity

It will be available in 26.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 10 Commit Notification 2026-01-13 17:08:39 UTC
Chiggy Wiggy committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/5331de43f79c44e58465f4a8d43b9b759d8e6108

tdf#168771 basctl: Convert traditional enums to enum class

It will be available in 26.8.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.