CDT  v4.2.0
инструменты разработчика
binary_extension.hpp
См. документацию.
1#pragma once
2
3#include "check.hpp"
4
5namespace eosio {
19 template <typename T>
20 class binary_extension {
21 public:
22 using value_type = T;
23
24 constexpr binary_extension() {}
25 constexpr binary_extension( const T& ext )
26 :_has_value(true)
27 {
28 ::new (&_data) T(ext);
29 }
30 constexpr binary_extension( T&& ext )
31 :_has_value(true)
32 {
33 ::new (&_data) T(std::move(ext));
34 }
36 template <typename... Args>
37 constexpr binary_extension( std::in_place_t, Args&&... args )
38 :_has_value(true)
39 {
40 ::new (&_data) T(std::forward<Args>(args)...);
41 }
42
43 constexpr binary_extension( const binary_extension& other )
44 :_has_value(other._has_value)
45 {
46 if( other._has_value ) ::new (&_data) T( *other );
47 }
48
49 constexpr binary_extension( binary_extension&& other )
50 :_has_value(other._has_value)
51 {
52 if( other._has_value ) {
53 ::new (&_data) T( *std::move(other) );
54 other._has_value = false;
55 }
56 }
57
59 ~binary_extension() { reset(); }
60
62 constexpr binary_extension& operator = (const binary_extension& other) {
63 if (has_value())
64 reset();
65
66 if (other.has_value()) {
67 ::new (&_data) T(*other);
68 _has_value = true;
69 }
70 return *this;
71 }
72
74 constexpr binary_extension& operator = (binary_extension&& other) {
75 if (has_value())
76 reset();
77
78 if (other.has_value()) {
79 ::new (&_data) T(*other);
80 _has_value = true;
81 other._has_value = false;
82 }
83 return *this;
84 }
86 constexpr explicit operator bool()const { return _has_value; }
88 constexpr bool has_value()const { return _has_value; }
89
91 constexpr T& value()& {
92 if (!_has_value) {
93 check(false, "cannot get value of empty binary_extension");
94 }
95 return _get();
96 }
97
99
101 constexpr const T& value()const & {
102 if (!_has_value) {
103 check(false, "cannot get value of empty binary_extension");
104 }
105 return _get();
106 }
107
111 template <typename U>
112 constexpr auto value_or( U&& def ) -> std::enable_if_t<std::is_convertible<U, T>::value, T&>& {
113 if (_has_value)
114 return _get();
115 return def;
116 }
117 constexpr T&& value_or()&& {
118 if (!_has_value)
119 return std::move(T());
120 _has_value = false;
121 return std::move(_get());
122 }
123 constexpr const T&& value_or()const&& {
124 if (!_has_value)
125 return std::move(T());
126 _has_value = false;
127 return std::move(_get());
128 }
129 constexpr T value_or()& {
130 if (!_has_value)
131 return T();
132 return _get();
133 }
134 constexpr T value_or()const& {
135 if (!_has_value)
136 return T();
137 return _get();
138 }
139
140 constexpr T* operator->() {
141 return &_get();
142 }
143 constexpr const T* operator->()const {
144 return &_get();
145 }
146
147 constexpr T& operator*()& {
148 return _get();
149 }
150 constexpr const T& operator*()const& {
151 return _get();
152 }
153 constexpr const T&& operator*()const&& {
154 return std::move(_get());
155 }
156 constexpr T&& operator*()&& {
157 return std::move(_get());
158 }
159
160 template<typename ...Args>
161 T& emplace(Args&& ... args)& {
162 if (_has_value) {
163 reset();
164 }
165
166 ::new (&_data) T( std::forward<Args>(args)... );
167 _has_value = true;
168
169 return _get();
170 }
171
172 void reset() {
173 if( _has_value ) {
174 _get().~value_type();
175 _has_value = false;
176 }
177 }
178
180
181 private:
182 bool _has_value = false;
183 typename std::aligned_storage<sizeof(T), alignof(T)>::type _data;
184
185 constexpr T& _get() {
186 return *reinterpret_cast<T*>(&_data);
187 }
188
189 constexpr const T& _get()const {
190 return *reinterpret_cast<const T*>(&_data);
191 }
192 };
193
195
206 template<typename DataStream, typename T>
207 inline DataStream& operator<<(DataStream& ds, const eosio::binary_extension<T>& be) {
208 ds << be.value_or();
209 return ds;
210 }
211
222 template<typename DataStream, typename T>
223 inline DataStream& operator>>(DataStream& ds, eosio::binary_extension<T>& be) {
224 if( ds.remaining() ) {
225 T val;
226 ds >> val;
227 be.emplace(val);
228 }
229 return ds;
230 }
231
233
234} // namespace eosio