Description
We are using variant-lite in a project alongside tl::optional and other header-only C++11+ compatibility libraries. To provide a unified interface for downstream users, we expose them under a std_compat namespace:
namespace std_compat
{
template <class T>
using optional = tl::optional<T>;
using tl::bad_optional_access;
using tl::in_place_t;
using tl::in_place;
using tl::nullopt;
using tl::nullopt_t;
using tl::make_optional;
using tl::swap;
}
namespace std_compat
{
template <class... Types>
using variant = nonstd::variant<Types...>;
using nonstd::bad_variant_access;
using nonstd::get;
using nonstd::get_if;
using nonstd::holds_alternative;
using nonstd::visit;
using nonstd::variant_npos;
using nonstd::variant_size;
using nonstd::variant_size_v;
using nonstd::variant_alternative;
using nonstd::variant_alternative_t;
}
Problem
-
monostate conflicts:
Both tl::optional and variant-lite require a monostate type.
On MSVC 17.10.35122 (with C++17 enabled), the CRT also provides std::monostate.
This results in three different monostate definitions that are not interchangeable, causing compilation errors when the libraries are used together.
-
bad_variant_access mismatch:
The MSVC CRT provides std::bad_variant_access.
variant-lite uses its own nonstd::bad_variant_access.
Third-party code using our std_compat::variant must catch both exceptions to be safe, which is error-prone and unintuitive.
Proposed solution:
Add configuration macros to variant-lite to allow users to override the monostate and bad_variant_access implementations with their own (or the standard library’s) versions.
For example:
#ifdef variant_CONFIG_BAD_VARIANT_ACCESS
using variant_CONFIG_BAD_VARIANT_ACCESS;
#else
class variant_nodiscard bad_variant_access : public ::std::exception
{
public:
#if variant_CPP11_OR_GREATER
virtual const char* what() const variant_noexcept variant_override
#else
virtual const char* what() const throw()
#endif
{
return "bad variant access";
}
};
#endif
#ifdef variant_CONFIG_MONOSTATE
using variant_CONFIG_MONOSTATE;
#else
class monostate {};
struct in_place_t {
explicit in_place_t() = default;
};
static constexpr in_place_t in_place{};
#endif
Benefits:
- Avoids duplicate/conflicting type definitions when integrating with other compatibility libraries.
- Allows seamless use of the standard library’s
monostate and bad_variant_access when available.
- Reduces exception-handling boilerplate for downstream users.
- Keeps variant-lite flexible without breaking existing behavior.
If this approach does not conflict with any existing design decisions or constraints in variant-lite, I’m happy to prepare and submit the implementation as a PR.
Description
We are using variant-lite in a project alongside
tl::optionaland other header-only C++11+ compatibility libraries. To provide a unified interface for downstream users, we expose them under astd_compatnamespace:Problem
monostateconflicts:Both
tl::optionaland variant-lite require a monostate type.On MSVC 17.10.35122 (with C++17 enabled), the CRT also provides
std::monostate.This results in three different
monostatedefinitions that are not interchangeable, causing compilation errors when the libraries are used together.bad_variant_accessmismatch:The MSVC CRT provides
std::bad_variant_access.variant-lite uses its own
nonstd::bad_variant_access.Third-party code using our
std_compat::variantmust catch both exceptions to be safe, which is error-prone and unintuitive.Proposed solution:
Add configuration macros to variant-lite to allow users to override the
monostateandbad_variant_accessimplementations with their own (or the standard library’s) versions.For example:
Benefits:
monostateandbad_variant_accesswhen available.If this approach does not conflict with any existing design decisions or constraints in variant-lite, I’m happy to prepare and submit the implementation as a PR.