Thursday, October 1, 2026

Practical Testing: 46 - Timer Queue timers at shutdownOver the past few episodes of “Practical Testing” I’ve been implementing some changes to the real-world, multi-threaded code that I’ve been testing, using and developing for over 20 years. These changes have been to enable controlled shutdown. The changes have been designed, stubbed out, unit tests written and then the changes were implemented in one of the two timer systems, the timer wheel. In this, the final episode in this set of changes, we implement the changes in the timer queue.📝Rambling Comments - Len Holgate's blog
Parsing compressed JSON at 40 GB/sA common way to store JSON data is to write one document per line. We call it NDJSON or JSON Lines. Log files, database exports and machine-learning datasets often come in this format. The files can be large, so we may compress them. {"id":1,"active":true,"user":{"name":"user_1","tags":["guest"]},"score":-3862,"note":"..."} {"id":2,"active":false,"user":{"name":"user_2","tags":["staff","admin"]},"score":8123,"note":"..."} How fast can you read such a file? I wrote … Continue reading Parsing compressed JSON at 40 GB/s📝Daniel Lemire's blog

If this page is useful, please consider donating a coffee

Wednesday, September 30, 2026

Transcoding UTF-8 to UTF-16 with replacement at gigabytes per secondOur software represents strings using the UTF-16 or the UTF-8 formats. Most text on the web is UTF-8, but Java, C# or JavaScript represents the strings as UTF-16 to the programmer. Sometimes we need to transcode (convert) strings. Your browser probably uses the simdutf library for validating or transcoding. It is part of the widely … Continue reading Transcoding UTF-8 to UTF-16 with replacement at gigabytes per second📝Daniel Lemire's blog
Practical Testing: 45 - Timer Wheel timers at shutdownThis is the latest new episode of “Practical Testing” where I write about the most recent changes to some real-world, multithreaded code that I’ve been testing, using and developing for over 20 years. Now that we have sorted out the design for how we will manage the concept of shutting down the timer system we “just” have to implement it. We’ll start by doing the required work for the timer wheel implementation.📝Rambling Comments - Len Holgate's blog

Tuesday, September 29, 2026

Practical Testing: 44 - Timers pending at shutdownThis is the latest new episode of “Practical Testing” where I write about the most recent changes to some real-world, multithreaded code that I’ve been testing, using and developing for over 20 years. As with most things that I’ve written on this blog over the years, the target audience is future me; if anyone else gets any value from anything then that’s a nice bonus. This set of changes, centre on how we handle shutting the timer system down.📝Rambling Comments - Len Holgate's blog
Using any C++ library in GodotGodot has become one of the most popular game engines of the last few years. It is free, open source under the MIT license, and small enough to download and start using in minutes. Most Godot games are written in GDScript, the engine’s own scripting language. Sooner or later, though, many projects need something that already exists as a C or C++ library: a simulation library, a database, a networking protocol, a machine learning runtime. GDScript cannot call native code, but Godot can load it through GDExtension , and godot-cpp , the official C++ bindings, lets you expose that code as regular engine classes. Writing the C++ code is the easy part. The hard part is the build: godot-cpp has to match your Godot version, and every library you add has to be compiled for each platform you ship to. In this post we give a short tour of Godot, explain how C++ extensions work, and show how to bring C++ libraries into a Godot game with Conan and godot-cpp 10, now available in ConanCenter. As an example we will use flecs , an Entity Component System library, to simulate 100,000 particles inside a Godot scene. Download the video 100,000 particles simulated with flecs inside a Godot scene, fleeing from the mouse cursor A Quick Introduction to Godot Godot is a general purpose engine for 2D and 3D games. Everything in a Godot project is built from two concepts: Nodes are the basic building blocks. Each node has a type ( Sprite2D , Camera3D , AudioStreamPlayer , Timer …), a set of properties you can edit in the Inspector, and callbacks such as _ready() or _process() that the engine calls during the game loop. Scenes are trees of nodes saved to disk as .tscn files. A scene can be a character, a menu or a whole level, and scenes can be instanced inside other scenes. Behavior is usually added by attaching a script to a node. GDScript is a Python-like language designed for the engine, and it is great for gameplay logic because changes show up immediately without a compile step. What makes Godot interesting for C++ developers is that the engine itself is written in C++, and it can load extensions written in C++ without being recompiled. A class that comes from one of these extensions becomes a regular engine class: it shows up in the editor next to the built-in nodes, with its properties in the Inspector, and GDScript can use it like any other node. The next section explains how these extensions work. Extending Godot with C++ There are two ways to add C++ code to Godot: Engine modules are compiled into the engine itself. They have full access to the internals, but you need to build and ship your own copy of Godot, including the editor and export templates for every platform. GDExtension loads a shared library ( .dll , .so , .dylib , or .wasm on the web) into an official, unmodified Godot build at runtime. The engine talks to the library through a stable C interface. GDExtension is the recommended approach for most projects, and it is how many popular plugins are distributed today. Because the C interface is verbose to use directly, the Godot team maintains godot-cpp , a C++ library that wraps it with an API very close to the one used inside the engine. It provides a C++ class for every engine class, such as Node2D , Sprite2D or Input . Your own classes are regular C++ code that derives from those classes. A node written with godot-cpp looks like this: #include namespace godot { class MyNode : public Node2D { GDCLASS ( MyNode , Node2D ) protected: static void _bind_methods () {} public: void _process ( double p_delta ) override { // runs every frame } }; } // namespace godot Since version 10.0, a single godot-cpp release works with any Godot version from 4.3 onwards. You pick one with the api_version build option, and godot-cpp generates its C++ classes from the API of that version. An extension built for Godot 4.3 also works in newer versions, but not in older ones, so you usually pick the oldest Godot version you want to support. Build targets and feature tags There is one more concept you need to know before building anything. godot-cpp is compiled for one of three targets , named after the Godot builds that load the library: template_debug : the default. Enables debug checks through the DEBUG_ENABLED definition. This library is loaded by the editor and by debug exports. template_release : for release exports, with the debug checks removed. editor : for libraries that are only loaded by the editor. Which library Godot loads is decided at runtime by a small .gdextension file. It maps feature tags to library paths. The debug tag matches the editor and debug exports, and the release tag matches release exports: [configuration] entry_symbol = "gdexample_library_init" compatibility_minimum = "4.7" [libraries] macos.debug = "res://bin/libgdexample.template_debug.dylib" macos.release = "res://bin/libgdexample.template_release.dylib" linux.debug = "res://bin/libgdexample.template_debug.so" linux.release = "res://bin/libgdexample.template_release.so" windows.debug = "res://bin/libgdexample.template_debug.dll" windows.release = "res://bin/libgdexample.template_release.dll" The usual workflow The Godot documentation recommends adding godot-cpp to your repository as a git submodule and building it together with your library using SCons. That works well for a first extension, but every project ends up compiling its own godot-cpp for each target, platform and architecture, and any third party library you wrap, such as a physics engine or a machine learning runtime, has to be vendored and built with matching flags for every platform Godot exports to. Both are exactly the kind of problem Conan was built to solve. Managing the Dependencies with Conan With the godot-cpp recipe in ConanCenter, godot-cpp becomes a regular package. The two parameters discussed above are Conan options: api_version : the Godot API version the bindings target, from 4.3 to 4.7 (the default). target : template_debug (the default), template_release or editor . Each combination is built once and then reused by every project that needs it, instead of being compiled inside each extension. Your GDExtension becomes just another C++ project with dependencies. Any of the more than 1,900 libraries in ConanCenter , or one you package yourself with a Conan recipe , can be added next to godot-cpp, and Conan builds all of them consistently for every platform you target. A Practical Example: A Swarm of 100,000 Particles To show how this works in practice, we will write a GDExtension that registers a new Swarm node. It simulates 100,000 particles that flee from the mouse cursor and bounce off the window edges, and draws all of them in a Godot scene. The simulation runs on flecs , an Entity Component System (ECS) library for C and C++. In an ECS, entities are plain ids, components are plain data structs attached to them, and systems are functions that run over every entity that has a given set of components. Components of the same type are stored together in memory, which makes iterating over large numbers of entities very fast. That is why ECS is a popular choice for simulations, crowds or bullet hell games. It is also the kind of work where native code pays off, since updating this many entities every frame is much faster in C++ than in GDScript. You can find the complete example in the Conan examples2 repository : $ git clone https://github.com/conan-io/examples2.git $ cd examples2/examples/libraries/godot-cpp/gdextension The src folder contains the extension code, and demo is a regular Godot project that loads it. Declaring the dependencies The conanfile.py requires godot-cpp and flecs from ConanCenter: from conan import ConanFile from conan.tools.cmake import CMake , CMakeToolchain , cmake_layout class GDExtensionExample ( ConanFile ): package_type = "shared-library" settings = "os" , "compiler" , "build_type" , "arch" generators = "CMakeDeps" def requirements ( self ): self . requires ( "godot-cpp/10.0.0" ) self . requires ( "flecs/4.1.6" ) def layout ( self ): cmake_layout ( self ) def generate ( self ): tc = CMakeToolchain ( self ) # Godot picks the library to load by its build "target", so we name # the output after the target godot-cpp was built with tc . cache_variables [ "GODOTCPP_TARGET" ] = str ( self . dependencies [ "godot-cpp" ]. options . target ) tc . generate () def build ( self ): cmake = CMake ( self ) cmake . configure () cmake . build () The only Godot specific detail is in generate() . We read the target option of the godot-cpp dependency and pass it to CMake, so the name of the library always matches the godot-cpp binary it was linked against. The CMakeLists.txt cmake_minimum_required ( VERSION 3.15 ) project ( gdexample LANGUAGES CXX ) find_package ( godot-cpp REQUIRED CONFIG ) find_package ( flecs REQUIRED CONFIG ) add_library ( gdexample SHARED src/register_types.cpp src/swarm.cpp ) target_link_libraries ( gdexample PRIVATE godot-cpp flecs::flecs_static ) # Output as demo/bin/libgdexample. . , the path the # demo/bin/gdexample.gdextension file points Godot to. The generator # expression prevents multi-config generators from adding a Release/ subfolder set_target_properties ( gdexample PROPERTIES OUTPUT_NAME "gdexample. ${ GODOTCPP_TARGET } " PREFIX "lib" LIBRARY_OUTPUT_DIRECTORY "$ ${ CMAKE_SOURCE_DIR } /demo/bin>" RUNTIME_OUTPUT_DIRECTORY "$ ${ CMAKE_SOURCE_DIR } /demo/bin>" ) This is a completely standard CMake project. The extension is a shared library that links godot-cpp and flecs statically, so there is a single library file to ship. We write it straight into demo/bin so Godot finds it without an extra copy step. Writing the node The Swarm class derives from Node2D and owns the flecs world. The components of each particle are plain structs. The GDCLASS macro adds the boilerplate that Godot’s class system needs, and _bind_methods() declares what Godot can see, in this case the count and flee_radius properties. Once the class is registered, they appear in the Inspector and can be used from GDScript. This is a simplified view of the class: struct Position { float x , y ; }; struct Velocity { float x , y ; }; class Swarm : public Node2D { GDCLASS ( Swarm , Node2D ) int count = 100000 ; double flee_radius = 150.0 ; flecs :: world world ; ... protected: static void _bind_methods () { ClassDB :: bind_method ( D_METHOD ( "set_count" , "count" ), & Swarm :: set_count ); ClassDB :: bind_method ( D_METHOD ( "get_count" ), & Swarm :: get_count ); ADD_PROPERTY ( PropertyInfo ( Variant :: INT , "count" ), "set_count" , "get_count" ); // ... and the same for flee_radius } ... }; The rest of the node connects both worlds. _ready() creates one flecs entity per particle and a flecs system that updates them. It also sets up a MultiMesh , which draws many instances of the same mesh in a single draw call, because one Godot node per particle would be far too heavy for 100,000 of them. Every frame, _process() hands the mouse position to flecs, runs the systems with world.progress() , and copies the resulting positions back into the MultiMesh. Again, this is a simplified view, and the full code is in the repository: void Swarm :: _ready () { // One entity per particle, with a Position and a Velocity component for ( int i = 0 ; i count ; i ++ ) { world . entity (). set Position > ({ ... }). set Velocity > ({ ... }); } // A system that runs for every entity with both components world . system Position , Velocity > ( "Move" ). each ([ this ]( flecs :: iter & it , size_t , Position & p , Velocity & v ) { // flee from the mouse, move, and bounce off the window edges }); // A MultiMeshInstance2D child node that draws all the particles ... } void Swarm :: _process ( double p_delta ) { mouse = get_local_mouse_position (); world . progress ( static_cast float > ( p_delta )); // Copy the position of every entity into the MultiMesh buffer render_query . each ([ & ]( const Position & p , const Velocity & v ) { ... }); multimesh -> set_buffer ( buffer ); } Registering the extension Finally, register_types.cpp registers the class when Godot loads the library: void initialize_gdexample_module ( ModuleInitializationLevel p_level ) { if ( p_level != MODULE_INITIALIZATION_LEVEL_SCENE ) { return ; } GDREGISTER_RUNTIME_CLASS ( Swarm ); } We register Swarm with GDREGISTER_RUNTIME_CLASS . By default, the code of a GDExtension class also runs inside the editor, so _ready() and _process() would start the simulation while you are editing the scene. A runtime class is only a placeholder in the editor: you can add it to a scene and set its properties, but its code only runs when the game is running. The same file defines gdexample_library_init() , the entry point named in the .gdextension file. It is a few lines of boilerplate that look the same in every extension. Building and running With everything in place, building the extension is a single command: $ conan build . --build = missing ... [ 100%] Linking CXX shared library .../demo/bin/libgdexample.template_debug.dylib [ 100%] Built target gdexample Conan resolves godot-cpp and flecs, downloads precompiled binaries from ConanCenter when they exist for your configuration, builds the rest from source, generates the CMake integration and finally builds the extension. Note: godot-cpp requires C++17. If your default profile uses an older standard, which is the case for MSVC, add -s compiler.cppstd=17 to the command. Now start Godot 4.7, click “Import” in the Project Manager, and select demo/project.godot . When the project opens, Godot reads bin/gdexample.gdextension , loads the library, and Swarm becomes available like any built-in node. You can find it in the “Create New Node” dialog, under Node2D : The main scene of the demo already contains a Swarm node. Selecting it shows count and flee_radius in the Inspector, the two properties we bound in _bind_methods() : Press Play to run the scene, and move the mouse over the window to push the particles around. Then stop it, change count or flee_radius in the Inspector, and play it again to see how the swarm behaves with more particles or a wider flee radius. Conclusion GDExtension and godot-cpp let you write engine classes in C++, and Conan takes care of building godot-cpp and any other C++ library your extension needs. This is also a big advantage when you distribute the extension: building it for every platform you ship to only takes changing the settings of the build. Note for Linux: By default, the extension links libstdc++ dynamically, so the target system must provide a version at least as new as the one used to build it. For broad compatibility, build the extension and its dependencies against a toolchain and system libraries compatible with the oldest distribution you intend to support. Alternatively, link libstdc++ statically and hide its symbols with a linker version script. Try the complete example and check the godot-cpp documentation to learn more about writing extensions. If you have any feedback or run into any issues, please let us know in the Conan GitHub repository . Happy game development! This post was written with AI assistance and reviewed by humans.📝Conan C/C++ Package Manager Blog

Monday, September 28, 2026

Framatome Intercontrôle – Custom Developments to Optimize Non Destructive Testing Procedures Using a Robotic ArmAbout Framatome Intercontrôle Intercontrôle is a subsidiary of Framatome, specializing in automated Non Destructive Testing (NDT), in particular for safety-critical components of the primary circuits in nuclear reactors. It has been a leader in this field of activity for more than 50 years. They develop, qualify, and operate their inspection equipment on-site. The team therefore […]📝Kitware Inc
Practical Testing: 43 - A performance tweakThis is the next in a series of blog posts, called “Practical Testing”, about testing real-world, multithreaded, code. Code that is in use for a long time goes through various evolutionary changes. The code that we feature in this series of articles is often the beating heart of server systems that are built with The Server Framework. Our many clients have varying performance requirements and changes for one client eventually feed back into the framework that is used by all of our clients.📝Rambling Comments - Len Holgate's blog
Using C++17 std::optionalLet’s take a pair of two types - what can you do with such composition? In this article, I’ll describe std::optional - a helper “vocabulary” type added in C++17. It’s a wrapper that either contains a value of your type or is empty. Let’s see where it can be useful and how you can use it. Updated in September 2026 with C++20, C++23, and C++26 changes. Intro By adding the boolean flag to other types, you can achieve a thing called “nullable types”. As mentioned, the flag is used to indicate whether the value is available or not. Such wrapper represents an object that might be empty in an expressive way (so not via comments :)) While you can achieve “null-ability” by using unique values (-1, infinity, nullptr ), it’s not as clear as the separate wrapper type. Alternatively, you could even use std::unique_ptr and treat the empty pointer as not initialized - this works, but comes with the cost of allocating memory for the object. Optional types - that come from functional programming world - bring type safety and expressiveness. Most of other languages have something similar: for example std::option in Rust, Optional in Java, Data.Maybe in Haskell. std::optional was added in C++17 and brings a lot of experience from boost::optional that was available for many years. Since C++17 you can just #include and use the type. Such wrapper is still a value type (so you can copy it, via deep copy). What’s more, std::optional doesn’t need to allocate any memory on the free store. std::optional is a part of C++ vocabulary types along with std::any , std::variant and std::string_view . When to use Usually, you can use an optional wrapper in the following scenarios: If you want to represent a nullable type nicely. Rather than using unique values (like -1 , nullptr , NO_VALUE or something) For example, user’s middle name is optional. You could assume that an empty string would work here, but knowing if a user entered something or not might be important. With std::optional you get more information. Return a result of some computation (processing) that fails to produce a value and is not an error. For example finding an element in a dictionary: if there’s no element under a key it’s not an error, but we need to handle the situation. To perform lazy-loading of resources. For example, a resource type has no default constructor, and the construction is substantial. So you can define it as std::optional (and you can pass it around the system), and then load only if needed later. To pass optional parameters into functions. I like the description from boost optional which summarizes when we should use the type: From the boost::optional documentation: When to use Optional It is recommended to use optional in situations where there is exactly one, clear (to all parties) reason for having no value of type T , and where the lack of value is as natural as having any regular value of T While sometimes the decision to use optional might be blurry, you shouldn’t use it for error handling. As it best suits the cases when the value is empty and it’s a normal state of the program. Basic Example Here’s a simple example of what you can do with optional: std :: optional std :: string > UI :: FindUserNick () { if ( nick_available ) return { mStrNickName }; return std :: nullopt ; // same as return { }; } // use: std :: optional std :: string > UserNick = UI -> FindUserNick (); if ( UserNick ) Show ( * UserNick ); In the above code we define a function that returns optional containing a string. If the user’s nickname is available, then it will return a string. If not, then it returns nullopt . Later we can assign it to an optional and check (it converts to bool ) if it contains any value or not. Optional defines operator* so we can easily access the contained value. In the following sections you’ll see how to create std::optional , operate on it, pass around and even what is the performance cost you might want to consider. The C++17 Series This article is part of my series about C++17 Library Utilities. Here’s the list of the other topics that I’ll cover: Refactoring with std::optional Using std::optional (this post) Error handling and std::optional About std::variant About std::any In place construction for std::optional , std::variant and std::any std::string_view Performance C++17 string searchers & conversion utilities Working with std::filesystem Even more: Show me your code: std::optional A Wall of Your std::optional Examples Menu Class - Example of Modern C++17 STL features Resources about C++17 STL: C++17 In Detail by Bartek! C++17 - The Complete Guide by Nicolai Josuttis C++ Fundamentals Including C++ 17 by Kate Gregory Practical C++14 and C++17 Features - by Giovanni Dicanio C++17 STL Cookbook by Jacek Galowicz OK, so let’s move to std::optional . std::optional Creation There are several ways to create std::optional : // empty: std :: optional int > oEmpty ; std :: optional float > oFloat = std :: nullopt ; // direct: std :: optional int > oInt ( 10 ); std :: optional oIntDeduced ( 10 ); // deduction guides // make_optional auto oDouble = std :: make_optional ( 3.0 ); auto oComplex = make_optional std :: complex double >> ( 3.0 , 4.0 ); // in_place std :: optional std :: complex double >> o7 { std :: in_place , 3.0 , 4.0 }; // will call vector with direct init of {1, 2, 3} std :: optional std :: vector int >> oVec ( std :: in_place , { 1 , 2 , 3 }); // copy/assign: auto oIntCopy = oInt ; As you can see in the above code sample, you have a lot of flexibility with the creation of optional. It’s very simple for primitive types and this simplicity is extended for even complex types. The in_place construction is especially interesting, and the tag std::in_place is also supported in other types like any and variant . For example, you can write: // https://godbolt.org/g/FPBSak struct Point { Point ( int a , int b ) : x ( a ), y ( b ) { } int x ; int y ; }; std :: optional Point > opt { std :: in_place , 0 , 1 }; // vs std :: optional Point > opt {{ 0 , 1 }}; This saves the creation of a temporary Point object. I’ll address std::in_place later in a separate post, so stay tuned. Returning std::optional If you return an optional from a function, then it’s very convenient to return just std::nullopt or the computed value. std :: optional std :: string > TryParse ( Input input ) { if ( input . valid ()) return input . asString (); return std :: nullopt ; } In the above example you can see that I return std::string computed from input.asString() and it’s wrapped in optional . If the value is unavailable then you can just return std::nullopt . Of course, you can also declare an empty optional at the beginning of your function and reassign if you have the computed value. So we could rewrite the above example as: std :: optional std :: string > TryParse ( Input input ) { std :: optional std :: string > oOut ; // empty if ( input . valid ()) oOut = input . asString (); return oOut ; } It probably depends on the context which version is better. I prefer short functions, so I’d chose the first option (with multiple returns). Accessing The Stored Value Probably the most important operation for optional (apart from creation) is the way how you can fetch the contained value. There are several options: operator* and operator-> - similar to iterators. Accessing an empty optional is undefined behavior in C++17–23. C++26 adds checks in hardened implementations; see the update section below. value() - returns the value, or throws std::bad_optional_access value_or(defaultVal) - returns the value if available, or defaultVal otherwise. To check if the value is present you can use has_value() method or just check if (optional) as optional is automatically converted to bool . Here’s an example: // by operator* std :: optional int > oint = 10 ; std :: cout "oint " * opt1 '\n' ; // by value() std :: optional std :: string > ostr ( "hello" ); try { std :: cout "ostr " ostr . value () '\n' ; } catch ( const std :: bad_optional_access & e ) { std :: cout e . what () " \n " ; } // by value_or() std :: optional double > odouble ; // empty std :: cout "odouble " odouble . value_or ( 10.0 ) '\n' ; So the most useful way is probably just to check if the value is there and then access it: // compute string function: std :: optional std :: string > maybe_create_hello (); // ... if ( auto ostr = maybe_create_hello (); ostr ) std :: cout "ostr " * ostr '\n' ; else std :: cout "ostr is null \n " ; std::optional Operations Let’s see what are other operations on the type: Changing the value If you have existing optional object, then you can easily change the contained value by using several operations like emplace , reset , swap , assign. If you assign (or reset) with a nullopt then if the optional contains a value its destructor will be called. Here’s a little summary: #include #include #include class UserName { public : explicit UserName ( const std :: string & str ) : mName ( str ) { std :: cout "UserName::UserName( \' " ; std :: cout mName " \' ) \n " ; } ~ UserName () { std :: cout "UserName::~UserName( \' " ; std :: cout mName " \' ) \n " ; } private : std :: string mName ; }; int main () { std :: optional UserName > oEmpty ; // emplace: oEmpty . emplace ( "Steve" ); // calls ~Steve and creates new Mark: oEmpty . emplace ( "Mark" ); // reset so it's empty again oEmpty . reset (); // calls ~Mark // same as: //oEmpty = std::nullopt; // assign a new value: oEmpty . emplace ( "Fred" ); oEmpty = UserName ( "Joe" ); } The code is available here: @Coliru Comparisons std::optional allows you to compare contained objects almost “normally”, but with a few exceptions when the operands are nullopt . See below: #include #include int main () { std :: optional int > oEmpty ; std :: optional int > oTwo ( 2 ); std :: optional int > oTen ( 10 ); std :: cout std :: boolalpha ; std :: cout ( oTen > oTwo ) " \n " ; std :: cout ( oTen oTwo ) " \n " ; std :: cout ( oEmpty oTwo ) " \n " ; std :: cout ( oEmpty == std :: nullopt ) " \n " ; std :: cout ( oTen == 10 ) " \n " ; } The above code generates: true // (oTen > oTwo) false // (oTen The code is available here: @Coliru Examples of std::optional Here are two a few longer examples where std::optional fits nicely. User name with an optional nickname and age #include #include class UserRecord { public : UserRecord ( const std :: string & name , std :: optional std :: string > nick , std :: optional int > age ) : mName { name }, mNick { nick }, mAge { age } { } friend std :: ostream & operator ( std :: ostream & stream , const UserRecord & user ); private : std :: string mName ; std :: optional std :: string > mNick ; std :: optional int > mAge ; }; std :: ostream & operator ( std :: ostream & os , const UserRecord & user ) { os user . mName ' ' ; if ( user . mNick ) { os * user . mNick ' ' ; } if ( user . mAge ) os "age of " * user . mAge ; return os ; } int main () { UserRecord tim { "Tim" , "SuperTim" , 16 }; UserRecord nano { "Nathan" , std :: nullopt , std :: nullopt }; std :: cout tim " \n " ; std :: cout nano " \n " ; } The code is available here: @Coliru Parsing ints from the command line #include #include #include std :: optional int > ParseInt ( char * arg ) { try { return { std :: stoi ( std :: string ( arg )) }; // or from_chars... } catch (...) { std :: cout "cannot convert \' " arg " \' to int! \n " ; } return { }; } int main ( int argc , char * argv []) { if ( argc >= 3 ) { auto oFirst = ParseInt ( argv [ 1 ]); auto oSecond = ParseInt ( argv [ 2 ]); if ( oFirst && oSecond ) { std :: cout "sum of " * oFirst " and " * oSecond ; std :: cout " is " * oFirst + * oSecond " \n " ; } } } The code is available here: @Coliru The above code uses optional to indicate if we performed the conversion or not. Note that we in fact converted exceptions handling into optional, so we skip the errors that might appear. This might be “controversial” as usually, we should report errors. C++17 also offers std::from_chars , which parses numbers without throwing exceptions or allocating memory. See my article C++ String Conversion: Exploring std::from_chars in C++17 to C++26 for examples, including a parser that returns std::optional . Other examples Representing other optional entries for your types. Like in the example of a user record. It’s better to write std::optonal rather than use a comment to make notes like // if the 'key is 0x7788 then it's empty or something :) Return values for Find*() functions (assuming you don’t care about errors, like connection drops, database errors or something) See more in: A Wall of Your std::optional Examples - C++ Stories Performance & Memory consideration When you use std::optional you’ll pay with increased memory footprint. At least one extra byte is needed. Conceptually your version of the standard library might implement optional as: template typename T > class optional { bool _initialized ; std :: aligned_storage_t sizeof ( T ), alignof ( T ) > _storage ; public : // operations }; In short optional just wraps your type, prepares a space for it and then adds one boolean parameter. This means it will extend the size of your Type according do the alignment rules. There was one comment about this construction : “And no standard library can implement optional this way (they need to use a union, because constexpr)”. So the code above is only to show an example, not real implementation. Alignment rules are important as The standard defines: Class template optional [optional.optional]: The contained value shall be allocated in a region of the optional storage suitably aligned for the type T. For example: // sizeof(double) = 8 // sizeof(int) = 4 std :: optional double > od ; // sizeof = 16 bytes std :: optional int > oi ; // sizeof = 8 bytes While bool type usually takes only one byte, the optional type need to obey the alignment rules and thus the whole wrapper is larger than just sizeof(YourType) + 1 byte . For example, if you have a type like: struct Range { std :: optional double > mMin ; std :: optional double > mMax ; }; it will take more space than when you use your custom type: struct Range { bool mMinAvailable ; bool mMaxAvailable ; double mMin ; double mMax ; }; In the first case, we’re using 32 bytes! The second version is 24 bytes. Test code using Compiler Explorer Here’s a great description about the performance and memory layout taken from boost documentation: Performance considerations - 1.67.0 . And in Efficient optional values | Andrzej’s C++ blog the author discusses how to write a custom optional wrapper that might be a bit faster I wonder if there’s a chance to do some compiler magic and reuse some space and fit this extra “initialized flag” inside the wrapped type. So no extra space would be needed. Migration from boost::optional std::optional was adapted directly from boost::optional , so you should see the same experience in both versions. Moving from one to another should be easy, but of course, there are little differences. In the paper: N3793 - A proposal to add a utility class to represent optional objects (Revision 4) - from 2013-10-03 I’ve found the following table (and I tried to correct it when possible with the current state). aspect std::optional boost::optional (as of 1.67.0 ) Move semantics yes no yes in current boost noexcept yes no yes in current boost hash support yes no a throwing value accessor yes yes literal type (can be used in constexpr expressions) yes no in place construction `emplace`, tag `in_place` emplace() , tags in_place_init_if_t , in_place_init_t , utility in_place_factory disengaged state tag nullopt none optional references C++17–23: no; C++26: yes ( optional ) yes conversion from optional to optional yes yes explicit convert to ptr ( get_ptr ) no yes deduction guides yes no Special case: optional and optional While you can use optional on any type you need to pay special attention when trying to wrap boolean or pointers. std::optional ob - what does it model? With such construction you basically have a tri-state bool. So if you really need it, then maybe it’s better to look for a real tri-state bool like boost::tribool . Whet’s more it might be confusing to use such type because ob converts to bool if there’s a value inside and *ob returns that stored value (if available). Similarly you have a similar confusion with pointers: // don't use like that! only an example! std :: optional int *> opi { new int ( 10 ) }; if ( opi && * opi ) { std :: cout ** opi std :: endl ; delete * opi ; } if ( opi ) std :: cout "opi is still not empty!" ; The pointer to int is naturally “nullable”, so wrapping it into optional makes it very hard to use. Changes in C++20, C++23, and C++26 C++17 was published a long time ago, let’s find out how std::optional evolved over the recent years: C++20: Comparisons and constexpr C++20 adds operator (spaceship) for optionals. For example: #include #include constexpr std :: optional int > empty ; constexpr std :: optional int > two = 2 ; constexpr std :: optional int > ten = 10 ; static_assert (( two ten ) 0 ); // compares the stored values static_assert (( empty two ) 0 ); // empty comes before a value static_assert (( empty empty ) == 0 ); The stored types must support the required comparisons. See the C++20 specification . C++17 already allowed constructing an optional from a value at compile time. P2231R1 added missing constexpr support for operations like emplace() , reset() , assignment, swapping, and converting constructors. It was adopted during C++23 work as a defect report against C++20 . For example, with that change we can write: #include constexpr int compute () { std :: optional int > value ; value . emplace ( 42 ); value . reset (); return value . value_or ( 7 ); } static_assert ( compute () == 7 ); See @Compiler Explorer The operations on the stored type must also work at compile time. C++23: Monadic operations C++23 adds three functions for chaining operations on optionals ( P0798R8 ): transform() applies a function to the stored value and wraps the result in an optional. and_then() calls a function that already returns an optional, without adding another optional around it. or_else() calls a fallback function when the optional is empty. The function returns an optional of the same type. transform() and and_then() skip the function call when the optional is empty. These functions do not catch exceptions. I covered them with examples in a separate article: How to Use Monadic Operations for std::optional in C++23 . C++23 also adds std::expected . Consider it when the caller needs to know why an operation failed, rather than just whether a value is available. C++26: Range support C++26 adds begin() and end() and makes optional a ranges view ( P3168R2 ). A loop over an optional runs once if there’s a value, or not at all if it’s empty: std :: optional int > value = 42 ; for ( int x : value ) std :: cout x '\n' ; // prints 42 once This also lets us use std::views::join on a range of optionals to visit the values and skip empty entries. C++26: Optional references C++26 adds std::optional ( P2988R12 ). It can refer to an existing object or be empty: int first = 10 ; int second = 20 ; std :: optional int &> ref { first }; * ref = 15 ; // changes first ref . emplace ( second ); // now refers to second * ref = 25 ; // changes second Notice that emplace() changes which object we refer to, while writing through *ref changes the object itself. The optional does not own the object or keep it alive. C++26: Hardened access With a hardened standard library, operator* and operator-> check that the optional has a value before accessing it ( P3471R4 ). Without hardening, accessing an empty optional this way still has undefined behavior. Use value() if you want an exception when the optional is empty. See here: #include #include #include int main () { std :: optional std :: string > nick = "SuperTim" ; std :: print ( "{} \n " , * nick ); // OK: contains a value std :: print ( "{} \n " , nick -> size ()); // OK: contains a value nick . reset (); // now empty try { std :: print ( "{} \n " , nick . value ()); } catch ( const std :: bad_optional_access & ) { std :: print ( "No nickname \n " ); } // fails the hardening check, comment this line //std::print("{}\n", *nick); } See @Compiler Explorer With the line uncommented, I’m getting: rogram stderr optional.h:524: libc++ Hardening assertion this->has_value() failed: optional operator* called on a disengaged value Program terminated with signal SIGABRT (6) For more see my C++26: Standard Library Hardening Experiments . Support for these C++26 features depends on your compiler and standard library. Wrap up Uff… ! it was a lot of text about optional, but still it’s not all :) Yet, we’ve covered the basic usage, creation and operations of this useful wrapper type. I believe we have a lot of cases where optional fits perfectly and much better than using some predefined values to represent nullable types. I’d like to remember the following things about std::optional : std::optional is a wrapper type to express “null-able” types. std::optional won’t use any dynamic allocation std::optional contains a value or it’s empty use operator * , operator-> , value() or value_or() to access the underlying value. std::optional is implicitly converted to bool so that you can easily check if it contains a value or not. In the next article I’ll try to explain error handling and why optional is maybe not the best choice there. I’d like to thank Patrice Roy ( @PatriceRoy1 ), Jacek Galowicz ( @jgalowicz ) and Andrzej Krzemienski ( akrzemi ) for finding time do do a quick review of this article!📝C++ Stories

Sunday, September 27, 2026

Saturday, September 26, 2026

Friday, September 25, 2026