expected
expected<T, E> is the error-handling primitive used by Vix conversion APIs.
It provides a predictable alternative to exceptions and integrates cleanly with strict parsing functions like to_int, to_float, and to_enum.
Header
#include <vix/conversion/Expected.hpp>Namespace:
vix::conversionWhy Vix Has Its Own expected
Vix conversion targets C++20, but std::expected is a C++23 feature.
This header provides a single abstraction:
- Use
std::expectedwhen the standard library actually supports it - Otherwise use a small C++20 fallback that implements the minimal API Vix needs
This guarantees the same public API for conversions across toolchains and language modes.
When std::expected Is Used
Vix will alias std::expected only if:
<expected>header exists- The library feature macro
__cpp_lib_expectedis defined __cpp_lib_expected >= 202202L
When those conditions are met:
template <typename T, typename E>
using expected = std::expected<T, E>;
template <typename E>
using unexpected = std::unexpected<E>;Otherwise, Vix uses its fallback types.
constexpr Behavior
In C++23 mode with std::expected, functions returning expected can be constexpr.
In fallback mode (C++20), the type is not a literal type, so constexpr would warn.
Vix standardizes this using:
#if VIX_CONVERSION_EXPECTED_IS_STD
#define VIX_EXPECTED_CONSTEXPR constexpr
#else
#define VIX_EXPECTED_CONSTEXPR inline
#endifSo conversion APIs can write:
[[nodiscard]] VIX_EXPECTED_CONSTEXPR expected<int, ConversionError>
to_int32(std::string_view input) noexcept;Public API Surface
The Vix fallback is intentionally minimal. It supports only what conversion code needs.
expected<T, E>
Main operations:
has_value()operator bool()value()accessorserror()accessors
unexpected<E>
Used to carry an error value:
error()accessorsmake_unexpected(E)helper
Basic Usage Pattern
auto r = vix::conversion::to_float64("3.14");
if (!r)
{
// failure path
auto err = r.error();
// inspect err.code, err.input, etc.
return;
}
// success path
double v = r.value();This style is:
- explicit
- branch-friendly
- exception-free
- easy to propagate
Creating Errors with make_unexpected
Vix provides a helper to build unexpected<E> consistently:
return make_unexpected(ConversionError{
ConversionErrorCode::InvalidFloat,
input
});This works in both modes:
- std::expected mode
- fallback mode
Notes About the Fallback Implementation
The fallback expected<T, E> is implemented as:
- A union storing either
TorE - A boolean flag
has_that selects which member is active - Placement-new constructors
- A destructor that destroys the active member
assert(...)guards onvalue()anderror()access
Important behavior:
value()asserts that the expected holds a valueerror()asserts that the expected holds an error
This matches the "debug-checked" style used in Vix: if you misuse the API, you get a clear assertion failure during development.
Design Philosophy
Vix conversion APIs are strict.
So error handling must be:
- explicit
- typed
- predictable
- portable across C++20 and C++23
expected<T, E> is the foundation that enables this style.