Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created June 28, 2017 20:16
Show Gist options
  • Save vittorioromeo/4d0dd32cbf2e9fb187ed573fcc28f043 to your computer and use it in GitHub Desktop.
Save vittorioromeo/4d0dd32cbf2e9fb187ed573fcc28f043 to your computer and use it in GitHub Desktop.
// generated with `unosolo`
// https://github.com/SuperV1234/unosolo
#pragma once
#include <utility>
#ifndef FWD
#define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#endif
#include <type_traits>
#define SCELTA_NOEXCEPT_AND_TRT_ENABLE_IF(m_condition, ...) \
noexcept(noexcept(__VA_ARGS__)) \
->::std::enable_if_t<m_condition, decltype(__VA_ARGS__)>
#define SCELTA_NOEXCEPT_AND_TRT(...) \
noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__)
#define SCELTA_RETURNS_ENABLE_IF(m_condition, ...) \
SCELTA_NOEXCEPT_AND_TRT_ENABLE_IF(__VA_ARGS__) \
{ \
return __VA_ARGS__; \
}
#define SCELTA_RETURNS(...) \
SCELTA_NOEXCEPT_AND_TRT(__VA_ARGS__) \
{ \
return __VA_ARGS__; \
}
#define SCELTA_NOEXCEPT_AND_RETURN_BODY(...) \
noexcept(noexcept(__VA_ARGS__)) \
{ \
return __VA_ARGS__; \
}
#include <type_traits>
namespace scelta
{
namespace impl
{
template <typename...>
struct linear_overloader
{
};
template <typename T, typename... Ts>
struct linear_overloader<T, Ts...> : T
{
private:
using U = linear_overloader<Ts...>;
U _u;
#define DEFINE_SELECT(m_refq) \
private: \
template <typename... Args, typename = decltype(std::declval<T m_refq>()( \
std::declval<Args>()...))> \
constexpr T m_refq select(int) m_refq noexcept \
{ \
return static_cast<T m_refq>(*this); \
} \
\
template <typename... Args> \
constexpr U m_refq select(...) m_refq noexcept \
{ \
return _u; \
} \
\
public: \
template <typename... Args> \
constexpr decltype(auto) operator()(Args&&... xs) m_refq \
{ \
return select<Args...>(0)(FWD(xs)...); \
}
DEFINE_SELECT(&)
DEFINE_SELECT(const&)
DEFINE_SELECT(&&)
#undef DEFINE_SELECT
public:
template <typename TFwd, typename... TFwds>
constexpr linear_overloader(TFwd&& x, TFwds&&... xs) noexcept(
std::is_nothrow_constructible_v<T, TFwd&&>&&
std::is_nothrow_constructible_v<U, TFwds&&...>)
: T{FWD(x)}, _u{FWD(xs)...}
{
}
};
}
template <typename... Ts>
constexpr auto linear_overload(Ts&&... xs) SCELTA_RETURNS(
impl::linear_overloader<std::remove_reference_t<Ts>...>{FWD(xs)...})
}
#include <cassert>
#include <utility>
#ifndef NDEBUG
#define SCELTA_CONSTEXPR_ASSERT(expr) \
(__builtin_expect(expr, true) ? void(0) : [] { assert(!#expr); }())
#else
#define SCELTA_CONSTEXPR_ASSERT(...) void(0)
#endif
#include <type_traits>
namespace scelta
{
namespace impl
{
template <typename... Ts>
struct overloader : Ts...
{
template <typename... Args>
constexpr overloader(Args&&... xs) noexcept(
(noexcept(Ts{FWD(xs)}) && ...))
: Ts{FWD(xs)}...
{
}
using Ts::operator()...;
};
}
template <typename... Ts>
constexpr auto overload(Ts&&... xs) SCELTA_RETURNS(
impl::overloader<std::remove_reference_t<Ts>...>{FWD(xs)...})
}
#include <type_traits>
namespace scelta::meta
{
template <typename Source, typename T>
using as_if_forwarded = std::conditional_t< //
std::is_lvalue_reference_v<Source>, //
std::remove_reference_t<T>&, //
std::remove_reference_t<T>&&>;
template <typename Source, typename T>
auto forward_like(T&& x)
SCELTA_RETURNS(static_cast<as_if_forwarded<Source, T&&>>(x))
}
namespace scelta::traits::impl
{
template <typename Trait>
struct dispatch
{
template <typename... Ts>
constexpr auto operator()(Ts&&... xs) const
SCELTA_RETURNS(
Trait{}(FWD(xs)...)
)
};
}
namespace scelta::traits::optional
{
template <typename>
struct access
{
template <typename Optional>
constexpr auto operator()(Optional&& o)
SCELTA_RETURNS(
*FWD(o)
)
};
template <typename T>
inline constexpr traits::impl::dispatch<access<T>> access_v{};
}
#include <type_traits>
namespace scelta::impl
{
template <typename Optional>
constexpr auto access_optional(Optional&& o)
SCELTA_RETURNS(
::scelta::traits::optional::access_v<std::decay_t<Optional>>(FWD(o))
)
}
namespace scelta::traits::adt
{
template <typename>
struct valid
{
template <typename... Variants>
constexpr auto operator()(Variants&&...)
{
return true;
}
};
template <typename T>
inline constexpr traits::impl::dispatch<valid<T>> valid_v{};
}
namespace scelta
{
struct nullopt_t
{
};
inline constexpr nullopt_t nullopt{};
}
namespace scelta::impl
{
template <typename... Ts>
constexpr auto to_nullopt(Ts&&...)
SCELTA_RETURNS(
::scelta::nullopt
)
template <typename Visitor>
constexpr auto visit_optional(Visitor&& visitor)
SCELTA_RETURNS(
FWD(visitor)()
)
template <typename F, typename Continuation, typename Optional>
constexpr auto call_with_optional(F&& f, Continuation&& c, Optional&& o)
SCELTA_RETURNS(
o ? FWD(c)(FWD(f)(meta::forward_like<Optional>(::scelta::impl::access_optional(o))))
: FWD(c)(FWD(f)(to_nullopt()))
)
template <typename Visitor, typename Optional, typename... Optionals>
constexpr auto visit_optional(
Visitor&& visitor, Optional&& o, Optionals&&... os) ->decltype(auto)
{
return
SCELTA_CONSTEXPR_ASSERT(
::scelta::traits::adt::valid_v<std::decay_t<Optional>>(o, os...)
),
call_with_optional(
[&](auto&& x) noexcept
{
return [&](auto&&... xs) SCELTA_RETURNS(
FWD(visitor)(FWD(x), FWD(xs)...)
);
},
[&](auto&& bound_visitor) SCELTA_RETURNS(
visit_optional(FWD(bound_visitor), FWD(os)...)
),
FWD(o)
);
}
}
#include <type_traits>
namespace scelta::meta
{
template <typename T>
struct always_false
{
using type = std::false_type;
};
template <typename T>
using always_false_t = typename always_false<T>::type;
template <typename T>
inline constexpr always_false_t<T> always_false_v{};
}
namespace scelta::traits::adt
{
namespace impl
{
struct visit_optional_t
{
template <typename Tag, typename... Ts>
constexpr auto operator()(Tag, Ts&&... xs)
SCELTA_RETURNS(
::scelta::impl::visit_optional(FWD(xs)...)
)
};
}
/*template <typename T>
struct visit
{
static_assert(meta::always_false_v<T>,
};*/
template <typename>
struct visit;
template <typename T>
inline constexpr traits::impl::dispatch<visit<T>> visit_v{};
}
#include <type_traits>
namespace scelta::impl
{
struct non_recursive_tag
{
};
template <typename Return>
struct recursive_tag
{
using return_type = Return;
};
template <typename Tag, typename Visitor, typename Variant, typename... Variants>
constexpr auto visit_homogenizer(Tag tag,
Visitor&& visitor, Variant&& variant, Variants&&... variants)
SCELTA_RETURNS(
::scelta::traits::adt::visit_v<std::decay_t<Variant>>(tag,
FWD(visitor), FWD(variant), FWD(variants)...)
)
}
#include <type_traits>
namespace scelta::meta
{
template <typename T>
using remove_cv_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename T>
using remove_cv_ref_ptr_t = std::remove_pointer_t<remove_cv_ref_t<T>>;
template <typename Source, typename T>
using copy_lvalue_reference_t =
std::conditional_t<std::is_lvalue_reference_v<Source>,
std::add_lvalue_reference_t<T>, T>;
template <typename Source, typename T>
using copy_rvalue_reference_t =
std::conditional_t<std::is_rvalue_reference_v<Source>,
std::add_rvalue_reference_t<T>, T>;
template <typename Source, typename T>
using copy_reference_t =
copy_lvalue_reference_t<Source, copy_rvalue_reference_t<Source, T>>;
template <typename Source, typename T>
using copy_const_t =
std::conditional_t<std::is_const_v<Source>, std::add_const_t<T>, T>;
template <typename Source, typename T>
using copy_volatile_t = std::conditional_t<std::is_volatile_v<Source>,
std::add_volatile_t<T>, T>;
template <typename Source, typename T>
using copy_cv_t = copy_volatile_t<Source, copy_const_t<Source, T>>;
template <typename Source, typename T>
using copy_pointer_t =
std::conditional_t<std::is_pointer_v<Source>, std::add_pointer_t<T>, T>;
template <typename Source, typename Destination>
class copy_cv_ptr_ref
{
private:
using S = std::remove_reference_t<Source>;
using D = remove_cv_ref_ptr_t<Destination>;
using U1 = copy_cv_t<S, D>;
using U2 = copy_pointer_t<S, U1>;
public:
using type = copy_reference_t<Source, U2>;
};
template <typename Source, typename Destination>
using copy_cv_ptr_ref_t =
typename copy_cv_ptr_ref<Source, Destination>::type;
}
#include <type_traits>
namespace scelta::meta
{
namespace impl
{
template <typename T>
using identity_check = T;
template <typename, typename T>
using identity_replace = T;
template < //
template <typename> typename OnCheck, //
template <typename, typename> typename OnReplace, //
typename Before, typename After, //
typename T //
>
struct apply : std::conditional< //
std::is_same_v<OnCheck<T>, Before>, //
OnReplace<T, After>, //
T>
{
};
template < //
template <typename> typename OnCheck, //
template <typename, typename> typename OnReplace, //
typename Before, typename After, //
template <typename...> typename T, typename... Ts //
>
struct apply<OnCheck, OnReplace, Before, After, T<Ts...>>
{
using type = T<
typename apply<OnCheck, OnReplace, Before, After, Ts>::type...>;
};
template < //
template <typename> typename OnCheck, //
template <typename, typename> typename OnReplace //
>
struct replace_all_impl
{
template <typename Before, typename After, typename T>
using apply_t =
typename apply<OnCheck, OnReplace, Before, After, T>::type;
};
using identity_replacer =
replace_all_impl<identity_check, identity_replace>;
using copy_cv_ref_ptr_replacer =
replace_all_impl<remove_cv_ref_ptr_t, copy_cv_ptr_ref_t>;
}
template <typename Before, typename After, typename T>
using replace_all_t = impl::identity_replacer::apply_t<Before, After, T>;
template <typename Before, typename After, typename T>
using replace_all_copy_cv_ptr_ref_t =
impl::copy_cv_ref_ptr_replacer::apply_t<Before, After, T>;
}
#include <type_traits>
namespace scelta::meta
{
namespace impl
{
template <typename F>
struct fn_ref_wrapper
{
static_assert(std::is_reference_v<F>);
F _f;
constexpr fn_ref_wrapper(F f) noexcept : _f{FWD(f)}
{
}
template <typename... Ts>
constexpr auto operator()(Ts&&... xs) const
SCELTA_RETURNS(
FWD(_f)(FWD(xs)...)
)
};
template <typename F>
struct y_combinator_wrapper : F
{
template <typename FFwd>
constexpr y_combinator_wrapper(FFwd&& f) noexcept(
noexcept(F(FWD(f))))
: F(FWD(f))
{
}
#define DEFINE_CALL_OPERATOR(m_refq) \
template <typename... Ts> \
constexpr auto operator()(Ts&&... xs) m_refq SCELTA_NOEXCEPT_AND_TRT( \
std::declval<F m_refq>()( \
std::declval<fn_ref_wrapper<y_combinator_wrapper m_refq>>(), \
FWD(xs)...)) \
{ \
return static_cast<F m_refq>(*this)( \
fn_ref_wrapper<y_combinator_wrapper m_refq>{ \
static_cast<y_combinator_wrapper m_refq>(*this)}, \
FWD(xs)...); \
}
DEFINE_CALL_OPERATOR(&)
DEFINE_CALL_OPERATOR(const&)
DEFINE_CALL_OPERATOR(&&)
#undef DEFINE_CALL_OPERATOR
};
}
template <typename F>
auto y_combinator(F&& f)
SCELTA_RETURNS(
impl::y_combinator_wrapper<std::decay_t<F>>(FWD(f))
)
}
#include <tuple>
namespace scelta::traits::adt
{
namespace impl
{
template <typename... Ts>
struct alternative_tuple
{
using type = std::tuple<Ts...>;
};
}
template <typename>
struct alternatives;
template <template <typename...> class T, typename... Ts>
struct alternatives<T<Ts...>> : impl::alternative_tuple<Ts...>
{
};
template <typename T>
inline constexpr traits::impl::dispatch<alternatives<T>> alternatives_v{};
template <typename T, std::size_t N>
using nth_alternative =
std::tuple_element_t<N, typename alternatives<T>::type>;
template <typename T>
using first_alternative = nth_alternative<T, 0>;
}
namespace scelta
{
template <typename Visitor>
constexpr auto visit(Visitor&& visitor)
SCELTA_RETURNS(FWD(visitor)())
namespace impl
{
constexpr void visit_impl() noexcept { return; }
template <typename Tag, typename Visitor, typename Variant, typename... Variants>
constexpr auto visit_impl(Tag tag,
Visitor&& visitor, Variant&& v, Variants&&... vs)
SCELTA_NOEXCEPT_AND_TRT(
impl::visit_homogenizer(tag, FWD(visitor), FWD(v), FWD(vs)...)
)
{
return
SCELTA_CONSTEXPR_ASSERT(
::scelta::traits::adt::valid_v<std::decay_t<Variant>>(v, vs...)
),
impl::visit_homogenizer(tag, FWD(visitor), FWD(v), FWD(vs)...);
}
}
template <typename... Ts>
constexpr auto visit(Ts&&... xs)
SCELTA_RETURNS(impl::visit_impl(impl::non_recursive_tag{}, FWD(xs)...))
}
namespace scelta
{
namespace impl
{
template <typename Visitor>
struct bound_visitor : Visitor
{
template <typename FwdVisitor>
constexpr bound_visitor(FwdVisitor&& visitor) noexcept(
noexcept(Visitor{FWD(visitor)}))
: Visitor{FWD(visitor)}
{
}
#define DEFINE_BOUND_VISITOR_CALL(m_refq) \
template <typename... Variants> \
constexpr auto operator()(Variants&&... variants) m_refq \
SCELTA_NOEXCEPT_AND_TRT( \
::scelta::visit(std::declval<Visitor m_refq>(), FWD(variants)...)) \
{ \
return ::scelta::visit( \
static_cast<Visitor m_refq>(*this), FWD(variants)...); \
}
DEFINE_BOUND_VISITOR_CALL(&)
DEFINE_BOUND_VISITOR_CALL(const&)
DEFINE_BOUND_VISITOR_CALL(&&)
#undef DEFINE_BOUND_VISITOR_CALL
};
template <typename Visitor>
constexpr auto make_bound_visitor(Visitor&& visitor)
SCELTA_RETURNS(
bound_visitor<std::decay_t<Visitor>>{FWD(visitor)}
)
}
template <typename... Fs>
constexpr auto match(Fs&&... fs)
SCELTA_RETURNS(
impl::make_bound_visitor(::scelta::overload(FWD(fs)...))
)
}
#ifndef SCELTA_SUPPORT_VARIANT_MPARK_DISABLE
#if __has_include(<mpark/variant.hpp>)
#include <mpark/variant.hpp>
#define SCELTA_SUPPORT_VARIANT_MPARK 1
namespace scelta::traits::adt
{
template <typename... Alts>
struct visit<::mpark::variant<Alts...>>
{
template <typename Tag, typename... Ts>
constexpr auto operator()(Tag, Ts&&... xs)
SCELTA_RETURNS(
::mpark::visit(FWD(xs)...)
)
};
template <typename... Alts>
struct valid<::mpark::variant<Alts...>>
{
template <typename... Ts>
constexpr auto operator()(Ts&&... xs)
SCELTA_RETURNS(
(!xs.valueless_by_exception() && ...)
)
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_VARIANT_STD_DISABLE
#if __has_include(<variant>)
#include <variant>
#define SCELTA_SUPPORT_VARIANT_STD 1
namespace scelta::traits::adt
{
template <typename... Alts>
struct visit<::std::variant<Alts...>>
{
template <typename Tag, typename... Ts>
constexpr auto operator()(Tag, Ts&&... xs)
SCELTA_RETURNS(
::std::visit(FWD(xs)...)
)
};
template <typename... Alts>
struct valid<::std::variant<Alts...>>
{
template <typename... Ts>
constexpr auto operator()(Ts&&... xs)
SCELTA_RETURNS(
(!xs.valueless_by_exception() && ...)
)
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_VARIANT_BOOST_DISABLE
#if __has_include(<boost/variant.hpp>)
#include <boost/variant.hpp>
#define SCELTA_SUPPORT_VARIANT_BOOST 1
namespace scelta::traits::adt
{
template <typename... Alts>
struct visit<::boost::variant<Alts...>>
{
template <typename Tag, typename... Ts>
constexpr auto operator()(Tag, Ts&&... xs)
SCELTA_RETURNS(
::boost::apply_visitor(FWD(xs)...)
)
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_VARIANT_TYPE_SAFE_DISABLE
#if __has_include(<type_safe/variant.hpp>) && \
__has_include(<type_safe/visitor.hpp>)
#include <cassert>
#include <type_safe/variant.hpp>
#include <type_safe/visitor.hpp>
#define SCELTA_SUPPORT_VARIANT_TYPE_SAFE 1
namespace scelta::impl
{
template <typename... Ts>
using any_is_nullvar = std::disjunction<
std::is_same<std::decay_t<Ts>, type_safe::nullvar_t>...>;
template <typename... Ts>
inline constexpr auto any_is_nullvar_v = any_is_nullvar<Ts...>::value;
template <typename T>
struct nullvar_ignorer
{
T _visitor;
static_assert(std::is_reference_v<T>);
template <typename TFwd>
constexpr nullvar_ignorer(TFwd&& visitor) : _visitor{FWD(visitor)}
{
}
template <typename... Ts,
std::enable_if_t<any_is_nullvar_v<Ts...>>* = nullptr>
constexpr void operator()(Ts&&...) const noexcept
{
assert(false);
__builtin_unreachable();
}
template <typename... Ts,
std::enable_if_t<!any_is_nullvar_v<Ts...>>* = nullptr>
constexpr auto operator()(Ts&&... xs)
SCELTA_RETURNS(FWD(_visitor)(FWD(xs)...))
};
template <typename T>
constexpr auto make_nullvar_ignorer(T&& x)
SCELTA_RETURNS(nullvar_ignorer<T&&>{FWD(x)})
}
namespace scelta::traits::adt
{
template <typename VariantPolicy, typename... Alternatives>
struct visit<::type_safe::basic_variant<VariantPolicy, Alternatives...>>
{
template <typename Tag, typename Visitor, typename... Ts>
constexpr auto operator()(Tag, Visitor&& v, Ts&&... xs)
SCELTA_RETURNS(
::type_safe::visit(
::scelta::impl::make_nullvar_ignorer(FWD(v)),
FWD(xs)...
)
)
};
template <typename VariantPolicy, typename... Alternatives>
struct valid<::type_safe::basic_variant<VariantPolicy, Alternatives...>>
{
template <typename... Ts>
constexpr auto operator()(Ts&&...)
SCELTA_RETURNS(
true // TODO: depends on policy
)
};
template <typename VariantPolicy, typename... Alternatives>
struct alternatives<
::type_safe::basic_variant<VariantPolicy, Alternatives...>>
: impl::alternative_tuple<Alternatives...>
{
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_VARIANT_EGGS_DISABLE
#if __has_include(<eggs/variant.hpp>)
#include <eggs/variant.hpp>
#define SCELTA_SUPPORT_VARIANT_EGGS 1
namespace scelta::traits::adt
{
template <typename... Alts>
struct visit<::eggs::variant<Alts...>>
{
template <typename Tag, typename... Ts>
constexpr auto operator()(Tag, Ts&&... xs)
SCELTA_RETURNS(
::eggs::variants::apply(FWD(xs)...)
)
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_OPTIONAL_BOOST_DISABLE
#if __has_include(<boost/optional.hpp>) && __has_include(<boost/none.hpp>)
#include <boost/optional.hpp>
#include <boost/none.hpp>
#define SCELTA_SUPPORT_OPTIONAL_BOOST 1
namespace scelta::traits::adt
{
template <typename T>
struct visit<::boost::optional<T>> : impl::visit_optional_t
{
};
}
#endif
#endif
#ifndef SCELTA_SUPPORT_OPTIONAL_TYPE_SAFE_DISABLE
#if __has_include(<type_safe/optional.hpp>)
#include <type_safe/optional.hpp>
#define SCELTA_SUPPORT_OPTIONAL_TYPE_SAFE 1
namespace scelta::traits
{
namespace adt
{
template <typename T>
struct visit<::type_safe::basic_optional<T>> : impl::visit_optional_t
{
};
template <typename T>
struct alternatives<::type_safe::basic_optional<T>>
: impl::alternative_tuple<typename T::value_type>
{
};
}
namespace optional
{
template <typename T>
struct access<::type_safe::basic_optional<T>>
{
template <typename Optional>
constexpr auto operator()(Optional&& o)
SCELTA_RETURNS(
FWD(o).value()
)
};
}
}
#endif
#endif
#ifndef SCELTA_SUPPORT_OPTIONAL_STD_DISABLE
#if __has_include(<optional>)
#include <optional>
#define SCELTA_SUPPORT_OPTIONAL_STD 1
namespace scelta::traits::adt
{
template <typename T>
struct visit<::std::optional<T>> : impl::visit_optional_t
{
};
}
#endif
#endif
namespace scelta::recursive
{
struct placeholder
{
placeholder() = delete;
placeholder(const placeholder&) = delete;
placeholder(placeholder&&) = delete;
placeholder& operator=(const placeholder&) = delete;
placeholder& operator=(placeholder&&) = delete;
};
namespace impl
{
template <typename After, typename T>
using replace_placeholders = //
meta::replace_all_copy_cv_ptr_ref_t<placeholder, After, T>;
}
}
#include <type_traits>
namespace scelta::recursive
{
namespace impl
{
template <typename T, typename = void>
struct original_type
{
using type = T;
};
template <typename T>
struct original_type<T, std::void_t<typename T::base_type>>
{
using type = typename T::base_type;
};
template <typename T>
using original_type_t = typename original_type<T>::type;
}
}
#include <type_traits>
namespace scelta::recursive
{
template <typename Return, typename Visitor, typename... Variants>
constexpr Return visit(Visitor&& visitor, Variants&&... variants)
{
return ::scelta::impl::visit_impl(
::scelta::impl::recursive_tag<Return>{}, FWD(visitor),
static_cast<meta::copy_cv_ptr_ref_t<Variants&&,
impl::original_type_t<std::decay_t<Variants>>>>(variants)...);
}
}
namespace scelta::recursive
{
namespace impl
{
template <typename Return, typename... Fs>
constexpr auto make_recursive_visitor(Fs&&... fs)
{
return meta::y_combinator(
[o = overload(FWD(fs)...)](auto self, auto&&... xs) mutable
-> Return
{
return o(
[&self](auto&&... vs) -> Return {
return ::scelta::recursive::visit<Return>(
self, FWD(vs)...);
},
FWD(xs)...);
}
);
}
}
template <typename Return, typename... Fs>
constexpr auto match(Fs&&... fs)
{
return [rv = impl::make_recursive_visitor<Return>(FWD(fs)...)](
auto&&... vs) mutable->Return
{
return ::scelta::recursive::visit<Return>(rv, FWD(vs)...);
};
}
}
#include <type_traits>
namespace scelta::recursive
{
template <typename>
class builder;
template <template <typename...> typename T, typename... Ts>
class builder<T<Ts...>>
{
public:
struct type;
template <typename U>
using resolve = impl::replace_placeholders<type, U>;
private:
using resolved_type = resolve<T<Ts...>>;
public:
struct type : resolved_type
{
using resolved_type::resolved_type;
using base_type = resolved_type;
};
};
template <typename Builder>
using type = typename Builder::type;
template <typename Builder, typename T>
using resolve = typename Builder::template resolve<T>;
}
namespace example
{
// First available variant type.
template <typename... Ts>
using variant =
#if defined(SCELTA_SUPPORT_VARIANT_STD)
::std::variant
#elif defined(SCELTA_SUPPORT_VARIANT_BOOST)
::boost::variant
#elif defined(SCELTA_SUPPORT_VARIANT_EGGS)
::eggs::variant
#elif defined(SCELTA_SUPPORT_VARIANT_MPARK)
::mpark::variant
#elif defined(SCELTA_SUPPORT_VARIANT_TYPE_SAFE)
::type_safe::variant
#else
#error "No variant type available."
#endif
<Ts...>;
// First available optional type.
template <typename... Ts>
using optional =
#if defined(SCELTA_SUPPORT_OPTIONAL_STD)
::std::optional
#elif defined(SCELTA_SUPPORT_OPTIONAL_BOOST)
::boost::optional
#elif defined(SCELTA_SUPPORT_OPTIONAL_TYPE_SAFE)
::type_safe::optional
#else
#error "No optional type available."
#endif
<Ts...>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment