ciabatta.hpp
Go to the documentation of this file.
1 // Copyright 2019 Gašper Ažman
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /*
16  * CHANGELOG:
17  * - Add explicit keyword to mixin constructor and remove
18  * default constructor and assignment operators.
19  * - Remove macro usage.
20  * - Invert the argument order on the curry struct template to
21  * support default template parameters.
22  * - Re-implement mixin struct so it doesn't require CRTP to compose a new mixin.
23  */
24 
25 #ifndef CIABATTA_CIABATTA_HPP
26 #define CIABATTA_CIABATTA_HPP
27 
29 
30 namespace ciabatta {
31 
32 template <typename MostDerived>
33 struct ciabatta_top { /* not a mixin */
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); }
39 };
40 
41 struct deferred {
42  deferred() = delete;
43 };
44 
45 namespace detail {
46 
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>;
51 };
52 
53 template <typename Concrete, template <class> class H>
54 struct chain_inherit<Concrete, H> {
55  using type = H<Concrete>;
56 };
57 
58 template <typename Concrete, template <class> class... Mixins>
59 using mixin_impl = typename chain_inherit<ciabatta_top<Concrete>, Mixins...>::type;
60 
61 } // namespace detail
62 
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)...) {}
68 };
69 
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;
73 };
74 
75 template <template <class...> class Mixin, typename... Args>
76 struct curry {
77  template <typename Base>
78  using mixin = Mixin<Base, Args...>;
79 };
80 
81 template <typename Interface, typename Base = ::ciabatta::deferred>
82 struct provides : Base, Interface {
83  template <typename B>
84  using mixin = typename curry<provides, Interface>::template mixin<B>;
85 
86  template <typename... Args>
87  constexpr explicit provides(Args&&... args) : Base(static_cast<decltype(args)>(args)...) {}
88 };
89 
90 } // namespace ciabatta
91 
93 
94 #endif
result
result[0]


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53