25 #ifndef CIABATTA_CIABATTA_HPP
26 #define CIABATTA_CIABATTA_HPP
32 template <
typename MostDerived>
34 using self_type = MostDerived;
35 [[nodiscard]] decltype(
auto) self() & {
return static_cast<self_type&
>(*this); }
36 [[nodiscard]] decltype(
auto) self() && {
return static_cast<self_type&&
>(*this); }
37 [[nodiscard]] decltype(
auto) self() const& {
return static_cast<const self_type&
>(*this); }
38 [[nodiscard]] decltype(
auto) self() const&& {
return static_cast<const self_type&&
>(*this); }
47 template <
typename Concrete,
template <
class>
class H,
template <
class>
class... Tail>
48 struct chain_inherit {
49 using result =
typename chain_inherit<Concrete, Tail...>::type;
50 using type = H<result>;
53 template <
typename Concrete,
template <
class>
class H>
54 struct chain_inherit<Concrete, H> {
55 using type = H<Concrete>;
58 template <
typename Concrete,
template <
class>
class... Mixins>
59 using mixin_impl =
typename chain_inherit<ciabatta_top<Concrete>, Mixins...>::type;
63 template <
typename Concrete,
template <
class>
class... Mixins>
64 struct mixin_base : ::ciabatta::detail::mixin_impl<Concrete, Mixins...> {
65 template <
typename... Rest>
66 constexpr
explicit mixin_base(Rest&&... rest)
67 : ::ciabatta::detail::mixin_impl<Concrete, Mixins...>(static_cast<decltype(rest)>(rest)...) {}
70 template <
template <
class>
class... Mixins>
71 struct mixin : ::ciabatta::mixin_base<mixin<Mixins...>, Mixins...> {
72 using ciabatta::mixin_base<mixin<Mixins...>, Mixins...>::mixin_base;
75 template <
template <
class...>
class Mixin,
typename... Args>
77 template <
typename Base>
78 using mixin = Mixin<Base, Args...>;
81 template <
typename Interface,
typename Base = ::ciabatta::deferred>
82 struct provides : Base, Interface {
84 using mixin =
typename curry<provides, Interface>::template mixin<B>;
86 template <
typename... Args>
87 constexpr
explicit provides(Args&&... args) : Base(static_cast<decltype(args)>(args)...) {}