Line data Source code
1 : /*! 2 : @file 3 : Defines `boost::hana::detail::ebo`. 4 : 5 : Copyright Louis Dionne 2013-2022 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 116527 : constexpr V const& ebo_get(ebo<K, V, true> const& x) 84 116527 : { 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 : 108 : namespace boost { namespace hana { 109 : namespace detail { 110 : using ::_hana::ebo; 111 : using ::_hana::ebo_get; 112 : } 113 : }} // end namespace boost::hana 114 : 115 : #endif // !BOOST_HANA_DETAIL_EBO_HPP