Skip to content

Upgrade to C++23 #1787

@heinezen

Description

@heinezen

Motivation

With gcc 15 and clang 20 now being released, which implement a lot of cool C++23 features, I think we can finally consider going for C++23. This isn't strictly required, but gives us access to a several nice features that have been added to the standard. We'll also make sure that we stay somewhat modern with our codebase.

Description

First step would be changine the required standard to 23 in our CMakeLists.txt:

openage/CMakeLists.txt

Lines 37 to 38 in 865bd54

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Theoretically our code should already be compatible. We don't use any of the removed features and there are not that many breaking changes. We would have to see how that turns out in practice though. There might also be a few new compiler warnings that we should fix. There might also be runtime issues.

We will also have to update our compiler and CMake dependencies. These ultimately depend on what C++23 features we want, but for a start we need a minimum of:

  • gcc 11
  • clang 12 (or 13?)
  • CMake 3.20

Ideas

Here's a (probably) list of things that have been added in C++23 and are interesting for us. We should probably spawn issues from these once we have added general C++23 support.

flat_map/flat_set

C++23 now supports ordered maps and sets that are optimized for fast access and small storage, while sacrificing some insertion/erasure speed. We don't have many uses for ordered maps, but they are used for the storage of some variables in the activity system in the game simulation, e.g. conditions for the XOR gateways (since these must be ordered). Since these maps also don't change much after initialization, they should be the perfect candidate for flat_map.

More info on flat_map/flat_set: https://www.sandordargo.com/blog/2022/10/05/cpp23-flat_map

Cleaner error handling with std::expected

For performance reasons and generally cleaner code, we already prefer a design that doesn't rely on throwing and catching exceptions, since handling those scenarios is pretty expensive. In some cases, we can't get around that though, usually for I/O operations and interfacing with external libraries. std::expected would allow us to encapsulate these situations a bit better. The idea behind it is similar to Rust's Result types. Instead of throwing an error, you return an object that either contains a valid result or an error. If it's an error, you can check for that and handle it accordingly.

A good starting point would probably be the AssetManager code that handled missing assets. Currently that requires a try-catch block which is a not really nice. We can also think about using std::expected in nyan to make game data handling more robust.

constexpr/consteval

constexpr and consteval can be used in more situations with C++23, which might give us more opportunities for compile time optimization. There's also if consteval now that can be used for evaluating branches at compile time. This could be useful for our templated code.

use C++ modules (especially std module)

std is now a module which we can add with import. Using std as a module could lead to faster build which is always nice. It could also lead to much reduced code complexity as a bonus. In the future, we could also define our own modules for our subcomponents, but that's not really on the agenda right now.

Format strings and <print> instead of streams

C++23 finally let's developers use a print function like a normal human being. Also formatting has been improved a lot, so we can probably replace a bunch of string/output streams with proper formatting types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: utilUtilitis and data structurescode qualityDoes not alter behavior, but beauty of our codeimprovementEnhancement of an existing componentlang: c++Done in C++ code

    Type

    No type

    Projects

    Status

    To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions