File indexing completed on 2025-09-16 08:46:20
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_VALUE_HOLDER_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_VALUE_HOLDER_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/poly_collection/detail/is_constructible.hpp>
0017 #include <boost/poly_collection/detail/is_equality_comparable.hpp>
0018 #include <boost/poly_collection/detail/is_nothrow_eq_comparable.hpp>
0019 #include <boost/poly_collection/exception.hpp>
0020 #include <new>
0021 #include <memory>
0022 #include <type_traits>
0023 #include <utility>
0024
0025 namespace boost{
0026
0027 namespace poly_collection{
0028
0029 namespace detail{
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 struct value_holder_emplacing_ctor_t{};
0060 constexpr value_holder_emplacing_ctor_t value_holder_emplacing_ctor=
0061 value_holder_emplacing_ctor_t();
0062
0063 template<typename T>
0064 class value_holder_base
0065 {
0066 protected:
0067 alignas(T) unsigned char s[sizeof(T)];
0068 };
0069
0070 template<typename T,typename U=T>
0071 class value_holder:public value_holder_base<T>
0072 {
0073 template<typename Q>
0074 using enable_if_not_emplacing_ctor_t=typename std::enable_if<
0075 !std::is_same<
0076 typename std::decay<Q>::type,value_holder_emplacing_ctor_t
0077 >::value
0078 >::type*;
0079
0080 using is_nothrow_move_constructible=std::is_nothrow_move_constructible<U>;
0081 using is_copy_constructible=std::is_copy_constructible<U>;
0082 using is_nothrow_copy_constructible=std::is_nothrow_copy_constructible<U>;
0083 using is_move_assignable=std::is_move_assignable<U>;
0084 using is_nothrow_move_assignable=std::is_nothrow_move_assignable<U>;
0085 using is_equality_comparable=detail::is_equality_comparable<U>;
0086 using is_nothrow_equality_comparable=detail::is_nothrow_equality_comparable<U>;
0087
0088 T* data()noexcept{return reinterpret_cast<T*>(&this->s);}
0089 const T* data()const noexcept
0090 {return reinterpret_cast<const T*>(&this->s);}
0091
0092 T& value()noexcept{return *static_cast<T*>(data());}
0093 const T& value()const noexcept{return *static_cast<const T*>(data());}
0094
0095 public:
0096 template<
0097 typename Allocator,
0098 enable_if_not_emplacing_ctor_t<Allocator> =nullptr
0099 >
0100 value_holder(Allocator& al,const U& x)
0101 noexcept(is_nothrow_copy_constructible::value)
0102 {allocator_copy(al,x);}
0103 template<
0104 typename Allocator,
0105 enable_if_not_emplacing_ctor_t<Allocator> =nullptr
0106 >
0107 value_holder(Allocator& al,U&& x)
0108 noexcept(is_nothrow_move_constructible::value)
0109 {std::allocator_traits<Allocator>::construct(al,data(),std::move(x));}
0110 template<
0111 typename Allocator,typename... Args,
0112 enable_if_not_emplacing_ctor_t<Allocator> =nullptr
0113 >
0114 value_holder(Allocator& al,value_holder_emplacing_ctor_t,Args&&... args)
0115 {std::allocator_traits<Allocator>::construct(
0116 al,data(),std::forward<Args>(args)...);}
0117 template<
0118 typename Allocator,
0119 enable_if_not_emplacing_ctor_t<Allocator> =nullptr
0120 >
0121 value_holder(Allocator& al,const value_holder& x)
0122 noexcept(is_nothrow_copy_constructible::value)
0123 {allocator_copy(al,x.value());}
0124 template<
0125 typename Allocator,
0126 enable_if_not_emplacing_ctor_t<Allocator> =nullptr
0127 >
0128 value_holder(Allocator& al,value_holder&& x)
0129 noexcept(is_nothrow_move_constructible::value)
0130 {std::allocator_traits<Allocator>::construct(
0131 al,data(),std::move(x.value()));}
0132
0133
0134
0135
0136
0137
0138 value_holder(const U& x)
0139 noexcept(is_nothrow_copy_constructible::value)
0140 {copy(x);}
0141 value_holder(U&& x)
0142 noexcept(is_nothrow_move_constructible::value)
0143 {::new ((void*)data()) T(std::move(x));}
0144 template<typename... Args>
0145 value_holder(value_holder_emplacing_ctor_t,Args&&... args)
0146 {::new ((void*)data()) T(std::forward<Args>(args)...);}
0147 value_holder(const value_holder& x)
0148 noexcept(is_nothrow_copy_constructible::value)
0149 {copy(x.value());}
0150 value_holder(value_holder&& x)
0151 noexcept(is_nothrow_move_constructible::value)
0152 {::new ((void*)data()) T(std::move(x.value()));}
0153
0154 value_holder& operator=(const value_holder& x)=delete;
0155 value_holder& operator=(value_holder&& x)
0156 noexcept(is_nothrow_move_assignable::value||!is_move_assignable::value)
0157
0158 {
0159 move_assign(std::move(x.value()));
0160 return *this;
0161 }
0162
0163 ~value_holder()noexcept{value().~T();}
0164
0165 friend bool operator==(const value_holder& x,const value_holder& y)
0166 noexcept(is_nothrow_equality_comparable::value)
0167 {
0168 return x.equal(y.value());
0169 }
0170
0171 private:
0172 template<typename Allocator,typename Q>
0173 void allocator_copy(Allocator& al,const Q& x)
0174 {
0175 allocator_copy(al,x,is_copy_constructible{});
0176 }
0177
0178 template<typename Allocator,typename Q>
0179 void allocator_copy(Allocator& al,const Q& x,std::true_type)
0180 {
0181 std::allocator_traits<Allocator>::construct(al,data(),x);
0182 }
0183
0184 template<typename Allocator,typename Q>
0185 void allocator_copy(Allocator&,const Q&,std::false_type)
0186 {
0187 throw not_copy_constructible{typeid(U)};
0188 }
0189
0190 template<typename Q>
0191 void copy(const Q& x){copy(x,is_copy_constructible{});}
0192
0193 template<typename Q>
0194 void copy(const Q& x,std::true_type)
0195 {
0196 ::new (data()) T(x);
0197 }
0198
0199 template<typename Q>
0200 void copy(const Q&,std::false_type)
0201 {
0202 throw not_copy_constructible{typeid(U)};
0203 }
0204
0205 void move_assign(T&& x){move_assign(std::move(x),is_move_assignable{});}
0206
0207 void move_assign(T&& x,std::true_type)
0208 {
0209 value()=std::move(x);
0210 }
0211
0212 void move_assign(T&& x,std::false_type)
0213 {
0214
0215
0216 static_assert(is_nothrow_move_constructible::value,
0217 "type should be move assignable or nothrow move constructible");
0218
0219 if(data()!=std::addressof(x)){
0220 value().~T();
0221 ::new (data()) T(std::move(x));
0222 }
0223 }
0224
0225 bool equal(const T& x)const{return equal(x,is_equality_comparable{});}
0226
0227 bool equal(const T& x,std::true_type)const
0228 {
0229 return value()==x;
0230 }
0231
0232 bool equal(const T&,std::false_type)const
0233 {
0234 throw not_equality_comparable{typeid(T)};
0235 }
0236 };
0237
0238 }
0239
0240 }
0241
0242 }
0243
0244 #endif