empty_value.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. Copyright 2018 Glen Joseph Fernandes
  3. (glenjofe@gmail.com)
  4. Distributed under the Boost Software License, Version 1.0.
  5. (http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. #ifndef BOOST_CORE_EMPTY_VALUE_HPP
  8. #define BOOST_CORE_EMPTY_VALUE_HPP
  9. #include <boost/config.hpp>
  10. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  11. #include <utility>
  12. #endif
  13. #if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40700)
  14. #define BOOST_DETAIL_EMPTY_VALUE_BASE
  15. #elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1800)
  16. #define BOOST_DETAIL_EMPTY_VALUE_BASE
  17. #elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1800)
  18. #define BOOST_DETAIL_EMPTY_VALUE_BASE
  19. #elif defined(BOOST_CLANG) && !defined(__CUDACC__)
  20. #if __has_feature(is_empty) && __has_feature(is_final)
  21. #define BOOST_DETAIL_EMPTY_VALUE_BASE
  22. #endif
  23. #endif
  24. #if defined(_MSC_VER)
  25. #pragma warning(push)
  26. #pragma warning(disable:4510)
  27. #endif
  28. namespace boost {
  29. template<class T>
  30. struct use_empty_value_base {
  31. enum {
  32. #if defined(BOOST_DETAIL_EMPTY_VALUE_BASE)
  33. value = __is_empty(T) && !__is_final(T)
  34. #else
  35. value = false
  36. #endif
  37. };
  38. };
  39. struct empty_init_t { };
  40. namespace empty_ {
  41. template<class T, unsigned N = 0,
  42. bool E = boost::use_empty_value_base<T>::value>
  43. class empty_value {
  44. public:
  45. typedef T type;
  46. #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
  47. empty_value() = default;
  48. #else
  49. BOOST_CONSTEXPR empty_value() { }
  50. #endif
  51. BOOST_CONSTEXPR empty_value(boost::empty_init_t)
  52. : value_() { }
  53. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  54. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  55. template<class U, class... Args>
  56. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args)
  57. : value_(std::forward<U>(value), std::forward<Args>(args)...) { }
  58. #else
  59. template<class U>
  60. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value)
  61. : value_(std::forward<U>(value)) { }
  62. #endif
  63. #else
  64. template<class U>
  65. BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value)
  66. : value_(value) { }
  67. template<class U>
  68. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value)
  69. : value_(value) { }
  70. #endif
  71. BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT {
  72. return value_;
  73. }
  74. BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT {
  75. return value_;
  76. }
  77. private:
  78. T value_;
  79. };
  80. #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  81. #if defined(BOOST_MSVC)
  82. /*
  83. This is a workaround to an MSVC bug when T is a nested class:
  84. https://developercommunity.visualstudio.com/t/Compiler-bug:-Incorrect-C2247-and-C2248/10690025
  85. */
  86. namespace detail {
  87. template<class T>
  88. class empty_value_base
  89. : public T {
  90. public:
  91. #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
  92. empty_value_base() = default;
  93. #else
  94. BOOST_CONSTEXPR empty_value_base() { }
  95. #endif
  96. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  97. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  98. template<class U, class... Args>
  99. BOOST_CONSTEXPR empty_value_base(U&& value, Args&&... args)
  100. : T(std::forward<U>(value), std::forward<Args>(args)...) { }
  101. #else
  102. template<class U>
  103. BOOST_CONSTEXPR empty_value_base(U&& value)
  104. : T(std::forward<U>(value)) { }
  105. #endif
  106. #else
  107. template<class U>
  108. BOOST_CONSTEXPR empty_value_base(const U& value)
  109. : T(value) { }
  110. template<class U>
  111. BOOST_CONSTEXPR empty_value_base(U& value)
  112. : T(value) { }
  113. #endif
  114. };
  115. } /* detail */
  116. #endif
  117. template<class T, unsigned N>
  118. class empty_value<T, N, true>
  119. #if defined(BOOST_MSVC)
  120. : detail::empty_value_base<T> {
  121. typedef detail::empty_value_base<T> empty_base_;
  122. #else
  123. : T {
  124. typedef T empty_base_;
  125. #endif
  126. public:
  127. typedef T type;
  128. #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
  129. empty_value() = default;
  130. #else
  131. BOOST_CONSTEXPR empty_value() { }
  132. #endif
  133. BOOST_CONSTEXPR empty_value(boost::empty_init_t)
  134. : empty_base_() { }
  135. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  136. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  137. template<class U, class... Args>
  138. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args)
  139. : empty_base_(std::forward<U>(value), std::forward<Args>(args)...) { }
  140. #else
  141. template<class U>
  142. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value)
  143. : empty_base_(std::forward<U>(value)) { }
  144. #endif
  145. #else
  146. template<class U>
  147. BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value)
  148. : empty_base_(value) { }
  149. template<class U>
  150. BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value)
  151. : empty_base_(value) { }
  152. #endif
  153. BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT {
  154. return *this;
  155. }
  156. BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT {
  157. return *this;
  158. }
  159. };
  160. #endif
  161. } /* empty_ */
  162. using empty_::empty_value;
  163. BOOST_INLINE_CONSTEXPR empty_init_t empty_init = empty_init_t();
  164. } /* boost */
  165. #if defined(_MSC_VER)
  166. #pragma warning(pop)
  167. #endif
  168. #endif