Lager provides various little utilities that are convenient when using it. They mostly revolve around functional programming and variant visitation.

using get_variant_t = std::decay_t<decltype(detail::as_variant(std::declval<T>()))>

Metafunction that returns the variant type that T is convertible to.

struct is_variant< T, decltype((void) detail::as_variant(std::declval< T > ()))> constexpr bool lager::is_variant_v = is_variant<T>::value

Alias for is_variant.

ZUG_INLINE_CONSTEXPR struct lager::noop_t lager::noop
ZUG_INLINE_CONSTEXPR struct lager::identity_t lager::identity
template <typename T>
constexpr auto lager::forward_variant(typename std::remove_reference<T>::type &v)

This forwards v so that if v is convertible to std::variant, the value is forwarded as a variant.

template <typename… Variants>
constexpr auto lager::match(Variants&&... vs)

Provides variant visitation in a syntactically more elegant way, as in:

auto v = std::variant<int, float, string>{...};
return match(v)(
  [](int x)    { ... },
  [](float x)  { ... },
  [](string x) { ... },

This also fixes also fixes visitation of variants when inheriting from the variant, which is broken in GNU libstdc++.

using variant_t = std::variant{...};
struct inherited_t : variant_t { using variant_t::variant_t; };

auto v = inhertited_t{};
match(v)(...); // this works!

template <class… Ts>
struct lager::visitor

Utility to make a variant visitor out of lambdas, using the overloaded pattern as describped in cppreference.

For alternative mechanisms for nice variant visitation, consider Scelta, Atria, or Boost.Hof.

template <typename T, typename Enable = void>
struct lager::is_variant

Metafunction that returns whether T is std::variant or is convertible to std::variant.

struct lager::noop_t

Function that takes any argument and does nothing.

struct lager::identity_t

Function that returns its first arguemnt.