expected lite: std::expected for C++11 in one header file
expected lite - C++23 expected objects for C++11 and later in a single-file header-only library
At a glance
- What is it?
- expected lite is a single-file header-only C++ library for value-or-error objects, written so that code targeting C++11 and later can use the semantics of the std::expected proposal without waiting for the standard library. It is distributed under the Boost Software License with no dependencies beyond the standard library.
- Who is it for?
- expected lite fits a team maintaining C++ code that has to build on compilers predating C++23 but wants the value-or-error return type that std::expected provides, and that prefers a vendored header to a package manager dependency.
- Can I use it commercially?
- Yes. BSL-1.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A value or an error, returned by value
expected lite is a single-file header-only library for objects that either represent a valid value or an error that you can pass by value, and it is intended for use with C++11 and later. The library is based on the std::expected proposal, and the README describes it as a partly implementation of that proposal for use with C++11 and later. The API surface is the familiar one. You get default and explicit construction, construction and assignment from a value convertible to the underlying type, copy and move construction and assignment from another expected of the same type, a test for the presence of a value, operators for unchecked access to the value or the error through a pointer or a reference, `value()` and `value_or()` for checked access to the value, relational operators, `swap()`, and various factory functions. Version 0.7.0 added the monadic operations of proposal p2505. The audience is a library or application author who wants the shape of the standard type today.
The example is small enough to check the semantics against
The README's example converts a string to an integer and returns either the value or a message:
#include "nonstd/expected.hpp"
#include <cstdlib>
#include <iostream>
#include <string>
using namespace nonstd;
using namespace std::literals;
auto to_int( char const * const text ) -> expected<int, std::string>
{
char * pos = nullptr;
auto value = strtol( text, &pos, 0 );
if ( pos != text ) return value;
else return make_unexpected( "'"s + text + "' isn't a number" );
}Two details are worth copying. The success path returns the `long` from `strtol` directly, converted into the expected, and the failure path uses `make_unexpected` with a `std::string` built from a literal, which is why the `using namespace std::literals` is there. The check `pos != text` is the standard trick for detecting that no digits were consumed. The compile and run instructions in the README show the same program being exercised with a number and with a word.
It prefers std::expected when the compiler has it
The configuration section is where this library is more interesting than a straight port. By default, expected lite uses `std::expected` if it is available and lets you use it through the namespace `nonstd`. You can override that default and explicitly request either implementation with a macro. Defining `nsel_CONFIG_SELECT_EXPECTED` to `nsel_EXPECTED_STD` selects `std::expected` as `nonstd::expected`, while `nsel_EXPECTED_NONSTD` selects expected lite's own `nonstd::expected`. The default is undefined, which has the same effect as defining it to `nsel_EXPECTED_DEFAULT`. There is also a `nsel_P0323R` macro, defaulting to 7, which sets the proposal revision number and controls the presence and behaviour of features. The practical effect is that a codebase can start on this library, keep compiling on old toolchains, and later switch to the standard type by changing a single define rather than by rewriting every call site.
A tweak header and a standard selection macro cover the rest
Two more configuration points matter. If the compiler supports `__has_include()`, expected lite supports the tweak header mechanism, and you provide your tweak header as `nonstd/expected.tweak.hpp` in a folder on the include search path, where you can define things such as `#define expected_CPLUSPLUS 201103L`. Separately, `-Dnsel_CPLUSPLUS=199711L` overrides the auto-detection of the supported C++ standard, which is what you need if a compiler does not set the `__cplusplus` macro correctly. There are also switches for the Windows lean and mean define, which is set automatically when `_MSC_VER` is present and can be turned off with `nsel_CONFIG_WIN32_LEAN_AND_MEAN` set to 0, and for compiling without exceptions, via `nsel_CONFIG_NO_EXCEPTIONS` set to 1. The repository carries a `test/` directory and an `example/` directory with `01-basic.cpp`, `02-required.cpp`, `03-no-exceptions.cpp`, and its own CMakeLists, so the no-exceptions path is a supported configuration with a worked example.
It deliberately does not provide reference-type expecteds
The README has a short and important list of what is not provided. Reference-type expecteds are not provided. expected lite does not honour triviality of the value and error types. And it does not handle overloaded address of operators. These are not bugs but scope decisions, and each one matters for a specific use. Honouring triviality is what lets the standard type be stored in a struct with no constructor and no destructor overhead, and code that stores an expected in a hot structure will notice the difference. Not handling overloaded address of operators removes a source of surprising behaviour with custom types, at the cost of not supporting types that overload it. If any of those three matter to your design, this is the wrong library, and the standard `std::expected` or a different implementation is the right answer.
One header, no dependencies, and a permissive licence
Installation is deliberately manual. expected lite is a single-file header-only library, and the instruction is to put `expected.hpp` directly into the project source tree or somewhere reachable from your project. It has no other dependencies than the C++ standard library, and the README is explicit about that. The distribution channel is broader than the manual instruction suggests, though, with badges for Conan, Vcpkg, a try-it-online link on Wandbox, and a Godbolt link, so a team that prefers a package manager can use one and a team that prefers vendoring can copy a header. The licence is the Boost Software License, with the text in LICENSE.txt, which is a permissive licence with no copyleft obligation. The repository also carries a `conanfile.py` for the Conan path, a `CMakeLists.txt` at the root, and a `CHANGES.txt` for the release history.
Where expected lite is the wrong tool
Two limits are structural. The first is that a single-header library is a maintenance liability that is not always acknowledged. A header copied into your source tree is now your code, and when the upstream fixes a bug or adds a feature you have no upstream to pull from, which is the point of the Vcpkg and Conan packages existing. Vendoring is fine for a project that owns its dependencies deliberately, and awkward for a project that expects to track upstream. The second is the C++11 floor. The library exists so that older toolchains can have the feature, and if your project already compiles with C++23 and links a standard library with `std::expected`, this library is a compatibility shim you do not need. The related question is what happens to a codebase that starts on expected lite and later moves to the standard type, since the two are not identical in every detail, and the proposal revision macro exists precisely because that difference is real.
Editorial conclusion
expected lite fits a team maintaining C++ code that has to build on compilers predating C++23 but wants the value-or-error return type that std::expected provides, and that prefers a vendored header to a package manager dependency. It is the wrong choice if your project already requires C++23, since the standard library version is free, and the wrong choice if you need reference-type expecteds or the triviality guarantees of the standard type, which the README lists as not provided. Before you adopt it, check the `nsel_CONFIG_SELECT_EXPECTED` default behaviour, because the library uses std::expected automatically when it is available, and read the C++ standard selection macros so you know which implementation you are actually compiling against.
Frequently asked questions
What is expected lite and what standard is it based on?
It is a single-file header-only C++ library for objects that either contain a valid value or an error you can pass by value, intended for C++11 and later. It is based on the std::expected proposal, and version 0.7.0 added the monadic operations from proposal p2505.
How do I install expected lite?
It is a single-file header-only library, so you put `expected.hpp` directly into the project source tree or somewhere reachable from your project. It has no dependencies other than the C++ standard library, and it is also distributed through Conan and Vcpkg.
Does expected lite use std::expected when it is available?
By default it uses `std::expected` if it is available and exposes it through the namespace `nonstd`. You can override that with the `nsel_CONFIG_SELECT_EXPECTED` macro, setting it to `nsel_EXPECTED_STD` or `nsel_EXPECTED_NONSTD`, and the `nsel_P0323R` macro, defaulting to 7, sets the proposal revision and controls which features are present.
What does expected lite not support?
Reference-type expecteds are not provided, expected lite does not honour triviality of the value and error types, and it does not handle overloaded address of operators. The `nsel_CONFIG_NO_EXCEPTIONS` macro set to 1 also lets you compile without exceptions, and the repository ships a `03-no-exceptions.cpp` example for that path.
What licence is expected lite distributed under?
It is distributed under the Boost Software License, with the licence text in LICENSE.txt, and the README states the library has no other dependencies than the C++ standard library.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nonstd-lite-expected-lite)Was this useful?