]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | /*! |
2 | @file | |
3 | Defines `boost::hana::detail::ebo`. | |
4 | ||
5 | @copyright Louis Dionne 2013-2016 | |
6 | Distributed under the Boost Software License, Version 1.0. | |
7 | (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | |
8 | */ | |
9 | ||
10 | #ifndef BOOST_HANA_DETAIL_EBO_HPP | |
11 | #define BOOST_HANA_DETAIL_EBO_HPP | |
12 | ||
13 | #include <boost/hana/config.hpp> | |
14 | #include <boost/hana/detail/intrinsics.hpp> | |
15 | ||
16 | ||
17 | namespace _hana { | |
18 | ////////////////////////////////////////////////////////////////////////// | |
19 | // ebo<K, V> | |
20 | // | |
21 | // Building block to implement the Empty Base Optimization (EBO). We | |
22 | // use a short name and define it in a short namespace to reduce | |
23 | // symbol lengths, since this type is used as a building block for | |
24 | // other widely used types such as `hana::pair`. | |
25 | // | |
26 | // When available, we use compiler intrinsics to reduce the number | |
27 | // of instantiations. | |
28 | // | |
29 | // `ebo` provides a limited set of constructors to reduce instantiations. | |
30 | // Also, the constructors are open-ended and they do not check for the | |
31 | // validity of their arguments, again to reduce compile-time costs. | |
32 | // Users of `ebo` should make sure that they only try to construct an | |
33 | // `ebo` from a compatible value. | |
34 | // | |
35 | // EBOs can be indexed using an arbitrary type. The recommended usage is | |
36 | // to define an integrap constant wrapper for the specific container using | |
37 | // EBO, and then index using that wrapper: | |
38 | // | |
39 | // template <int> struct idx; // wrapper for tuple | |
40 | // template <typename ...T> | |
41 | // struct tuple : ebo<idx<0>, T0>, ebo<idx<1>, T1>, ... { }; | |
42 | // | |
43 | // The reason for defining one wrapper per container is to avoid any issues | |
44 | // that can arise when using `ebo_get`, which casts to the base class. If | |
45 | // `tuple` and `pair` are inheritting from `ebo`s with the same indexing | |
46 | // scheme, trying to use `ebo_get` on a tuple of pairs will trigger an | |
47 | // ambiguous base class conversion, since both tuple and pair inherit | |
48 | // from `ebo`s with the same keys. | |
49 | ////////////////////////////////////////////////////////////////////////// | |
50 | template <typename K, typename V, bool = | |
51 | BOOST_HANA_TT_IS_EMPTY(V) && !BOOST_HANA_TT_IS_FINAL(V) | |
52 | > | |
53 | struct ebo; | |
54 | ||
55 | // Specialize storage for empty types | |
56 | template <typename K, typename V> | |
57 | struct ebo<K, V, true> : V { | |
58 | constexpr ebo() { } | |
59 | ||
60 | template <typename T> | |
61 | explicit constexpr ebo(T&& t) | |
62 | : V(static_cast<T&&>(t)) | |
63 | { } | |
64 | }; | |
65 | ||
66 | // Specialize storage for non-empty types | |
67 | template <typename K, typename V> | |
68 | struct ebo<K, V, false> { | |
69 | constexpr ebo() : data_() { } | |
70 | ||
71 | template <typename T> | |
72 | explicit constexpr ebo(T&& t) | |
73 | : data_(static_cast<T&&>(t)) | |
74 | { } | |
75 | ||
76 | V data_; | |
77 | }; | |
78 | ||
79 | ////////////////////////////////////////////////////////////////////////// | |
80 | // ebo_get | |
81 | ////////////////////////////////////////////////////////////////////////// | |
82 | template <typename K, typename V> | |
83 | constexpr V const& ebo_get(ebo<K, V, true> const& x) | |
84 | { return x; } | |
85 | ||
86 | template <typename K, typename V> | |
87 | constexpr V& ebo_get(ebo<K, V, true>& x) | |
88 | { return x; } | |
89 | ||
90 | template <typename K, typename V> | |
91 | constexpr V&& ebo_get(ebo<K, V, true>&& x) | |
92 | { return static_cast<V&&>(x); } | |
93 | ||
94 | ||
95 | template <typename K, typename V> | |
96 | constexpr V const& ebo_get(ebo<K, V, false> const& x) | |
97 | { return x.data_; } | |
98 | ||
99 | template <typename K, typename V> | |
100 | constexpr V& ebo_get(ebo<K, V, false>& x) | |
101 | { return x.data_; } | |
102 | ||
103 | template <typename K, typename V> | |
104 | constexpr V&& ebo_get(ebo<K, V, false>&& x) | |
105 | { return static_cast<V&&>(x.data_); } | |
106 | } // end namespace _hana | |
107 | ||
1e59de90 | 108 | namespace boost { namespace hana { |
b32b8144 FG |
109 | namespace detail { |
110 | using ::_hana::ebo; | |
111 | using ::_hana::ebo_get; | |
112 | } | |
1e59de90 | 113 | }} // end namespace boost::hana |
b32b8144 FG |
114 | |
115 | #endif // !BOOST_HANA_DETAIL_EBO_HPP |