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