ebo.hpp 3.8 KB

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