16template <
typename... Types>
20 static constexpr Tag
Empty = 0;
40 copy_construct_from(other);
46 move_construct_from(other);
54 variant &operator=(
const variant &other)
FL_NOEXCEPT {
58 copy_construct_from(other);
68 move_construct_from(other);
97 template <
typename T,
typename... Args>
115 template <
typename T>
bool is()
const FL_NOEXCEPT {
116 return _tag == type_to_tag<T>();
120 if (!is<T>())
return nullptr;
126 template <
typename T>
const T *ptr()
const FL_NOEXCEPT {
127 if (!is<T>())
return nullptr;
155 template <
typename T>
bool equals(
const T &other)
const FL_NOEXCEPT {
156 if (
auto p = ptr<T>()) {
163 template <
typename Visitor>
void visit(Visitor &visitor)
FL_NOEXCEPT {
168 using Fn = void (*)(
void *, Visitor &);
173 static constexpr Fn table[] = {
174 &variant::template visit_fn<Types, Visitor>...};
178 size_t index = _tag - 1;
179 if (index <
sizeof...(Types)) {
180 table[index](&_storage, visitor);
184 template <
typename Visitor>
void visit(Visitor &visitor)
const FL_NOEXCEPT {
189 using Fn = void (*)(
const void *, Visitor &);
192 static constexpr Fn table[] = {
193 &variant::template visit_fn_const<Types, Visitor>...};
197 size_t index = _tag - 1;
198 if (index <
sizeof...(Types)) {
199 table[index](&_storage, visitor);
205 template <
typename T,
typename Visitor>
206 static void visit_fn(
void *storage, Visitor &v)
FL_NOEXCEPT {
210 v.accept(*typed_ptr);
213 template <
typename T,
typename Visitor>
214 static void visit_fn_const(
const void *storage, Visitor &v)
FL_NOEXCEPT {
218 v.accept(*typed_ptr);
223 using Fn = void (*)(
void *);
226 static constexpr Fn table[] = {&variant::template destroy_fn<Types>...};
228 table[_tag - 1](&_storage);
233 template <
typename T>
static void destroy_fn(
void *storage)
FL_NOEXCEPT {
241 void copy_construct_from(
const variant &other)
FL_NOEXCEPT {
242 using Fn = void (*)(
void *,
const variant &);
245 static constexpr Fn table[] = {&variant::template copy_fn<Types>...};
246 table[other._tag - 1](&_storage, other);
251 template <
typename T>
252 static void copy_fn(
void *storage,
const variant &other)
FL_NOEXCEPT {
256 new (storage) T(*source_ptr);
260 void move_construct_from(variant &other)
FL_NOEXCEPT {
261 using Fn = void (*)(
void *, variant &);
264 static constexpr Fn table[] = {&variant::template move_fn<Types>...};
265 table[other._tag - 1](&_storage, other);
271 template <
typename T>
static void move_fn(
void *storage, variant &other)
FL_NOEXCEPT {
275 new (storage) T(
fl::move(*source_ptr));
285 template <
typename T>
static constexpr Tag type_to_tag()
FL_NOEXCEPT {
286 return type_to_tag_impl<T, Types...>
::value;
290 template <
typename T,
typename... Ts>
struct type_to_tag_impl;
292 template <
typename T>
struct type_to_tag_impl<T> {
293 static constexpr Tag
value = 0;
296 template <
typename T,
typename U,
typename... Rest>
297 struct type_to_tag_impl<T, U, Rest...> {
298 static constexpr Tag
value =
301 : (type_to_tag_impl<T, Rest...>
::value == 0
303 : type_to_tag_impl<T, Rest...>
::value + 1);
306 template <
typename T,
typename... Args>
void construct(Args &&...
args)
FL_NOEXCEPT {
308 _tag = type_to_tag<T>();