aboutsummaryrefslogtreecommitdiff
path: root/third-party
diff options
context:
space:
mode:
authorJames Ward <james.ward@arm.com>2020-09-25 11:43:21 +0100
committerJames Ward <james.ward@arm.com>2020-09-30 08:41:31 +0000
commit22a4e1539aca7d39d7abc932f0a4d0b27beedf80 (patch)
tree95152943571413af5a3b550ac391bb17f258feef /third-party
parentba3ef18cb6117c49fcdbf177dce5991d6d679cbc (diff)
downloadarmnn-22a4e1539aca7d39d7abc932f0a4d0b27beedf80.tar.gz
IVGCVSW-4519 Remove Boost Variant and apply_visitor variant
* add mapbox/variant third party package Signed-off-by: James Ward <james.ward@arm.com> Change-Id: I181302780edd9dace40f158a11327316a12ce69a
Diffstat (limited to 'third-party')
-rw-r--r--third-party/mapbox/LICENSE25
-rw-r--r--third-party/mapbox/LICENSE_1_0.txt23
-rw-r--r--third-party/mapbox/README.md248
-rw-r--r--third-party/mapbox/optional.hpp74
-rw-r--r--third-party/mapbox/recursive_wrapper.hpp122
-rw-r--r--third-party/mapbox/variant.hpp1053
-rw-r--r--third-party/mapbox/variant_cast.hpp85
-rw-r--r--third-party/mapbox/variant_io.hpp45
-rw-r--r--third-party/mapbox/variant_visitor.hpp43
9 files changed, 1718 insertions, 0 deletions
diff --git a/third-party/mapbox/LICENSE b/third-party/mapbox/LICENSE
new file mode 100644
index 0000000000..6c4ce40d5a
--- /dev/null
+++ b/third-party/mapbox/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) MapBox
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+- Neither the name "MapBox" nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/third-party/mapbox/LICENSE_1_0.txt b/third-party/mapbox/LICENSE_1_0.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/third-party/mapbox/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third-party/mapbox/README.md b/third-party/mapbox/README.md
new file mode 100644
index 0000000000..6bf97f0c45
--- /dev/null
+++ b/third-party/mapbox/README.md
@@ -0,0 +1,248 @@
+# Mapbox Variant
+
+An header-only alternative to `boost::variant` for C++11 and C++14
+
+[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant)
+[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant)
+[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master&service=github)](https://coveralls.io/r/mapbox/variant?branch=master)
+
+## Introduction
+
+Variant's basic building blocks are:
+
+- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
+- `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants
+- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type
+- `get<T>()` - a function to directly unwrap a variant's underlying type
+- `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant
+
+### Basic Usage - HTTP API Example
+
+Suppose you want to represent a HTTP API response which is either a JSON result or an error:
+
+```c++
+struct Result {
+ Json object;
+};
+
+struct Error {
+ int32_t code;
+ string message;
+};
+```
+
+You can represent this at type level using a variant which is either an `Error` or a `Result`:
+
+```c++
+using Response = variant<Error, Result>;
+
+Response makeRequest() {
+ return Error{501, "Not Implemented"};
+}
+
+Response ret = makeRequest();
+```
+
+To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
+
+```c++
+ret.match([] (Result r) { print(r.object); },
+ [] (Error e) { print(e.message); });
+```
+
+Instead of using the variant's convenience `.match` pattern matching function you can create a type visitor functor and use `apply_visitor` manually:
+
+```c++
+struct ResponseVisitor {
+ void operator()(Result r) const {
+ print(r.object);
+ }
+
+ void operator()(Error e) const {
+ print(e.message);
+ }
+};
+
+ResponseVisitor visitor;
+apply_visitor(visitor, ret);
+```
+
+In both cases the compiler makes sure you handle all types the variant can represent at compile.
+
+### Recursive Variants - JSON Example
+
+[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
+
+```c++
+struct String { string value; };
+struct Number { double value; };
+struct True { };
+struct False { };
+struct Null { };
+struct Array { vector<?> values; };
+struct Object { unordered_map<string, ?> values; };
+```
+
+This works for primitive types but how do we represent recursive types such as `Array` which can hold multiple elements and `Array` itself, too?
+
+For these use cases Variant provides a `recursive_wrapper` helper type which lets you express recursive Variants.
+
+```c++
+struct String { string value; };
+struct Number { double value; };
+struct True { };
+struct False { };
+struct Null { };
+
+// Forward declarations only
+struct Array;
+struct Object;
+
+using Value = variant<String, Number, True, False, Null, recursive_wrapper<Array>, recursive_wrapper<Object>>;
+
+struct Array {
+ vector<Value> values;
+};
+
+struct Object {
+ unordered_map<string, Value> values;
+};
+```
+
+For walking the JSON representation you can again either create a `JSONVisitor`:
+
+```c++
+struct JSONVisitor {
+
+ void operator()(Null) const {
+ print("null");
+ }
+
+ // same for all other JSON types
+};
+
+JSONVisitor visitor;
+apply_visitor(visitor, json);
+```
+
+Or use the convenience `.match` pattern matching function:
+
+```c++
+json.match([] (Null) { print("null"); },
+ ...);
+```
+
+To summarize: use `recursive_wrapper` to represent recursive "tree-like" representations:
+
+```c++
+struct Empty { };
+struct Node;
+
+using Tree = variant<Empty, recursive_wrapper<Node>>;
+
+struct Node {
+ uint64_t value;
+}
+```
+
+### Advanced Usage Tips
+
+Creating type aliases for variants is a great way to reduce repetition.
+Keep in mind those type aliases are not checked at type level, though.
+We recommend creating a new type for all but basic variant usage:
+
+```c++
+// the compiler can't tell the following two apart
+using APIResult = variant<Error, Result>;
+using FilesystemResult = variant<Error, Result>;
+
+// new type
+struct APIResult : variant<Error, Result> {
+ using Base = variant<Error, Result>;
+ using Base::Base;
+}
+```
+
+## Why use Mapbox Variant?
+
+Mapbox variant has the same speedy performance of `boost::variant` but is
+faster to compile, results in smaller binaries, and has no dependencies.
+
+For example on OS X 10.9 with clang++ and libc++:
+
+Test | Mapbox Variant | Boost Variant
+---- | -------------- | -------------
+Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB
+Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K
+Time to compile header | 185 ms | 675 ms
+
+(Numbers from an older version of Mapbox variant.)
+
+## Goals
+
+Mapbox `variant` has been a very valuable, lightweight alternative for apps
+that can use c++11 or c++14 but that do not want a boost dependency.
+Mapbox `variant` has also been useful in apps that do depend on boost, like
+mapnik, to help (slightly) with compile times and to majorly lessen dependence
+on boost in core headers. The original goal and near term goal is to maintain
+external API compatibility with `boost::variant` such that Mapbox `variant`
+can be a "drop in". At the same time the goal is to stay minimal: Only
+implement the features that are actually needed in existing software. So being
+an "incomplete" implementation is just fine.
+
+Currently Mapbox variant doesn't try to be API compatible with the upcoming
+variant standard, because the standard is not finished and it would be too much
+work. But we'll revisit this decision in the future if needed.
+
+If Mapbox variant is not for you, have a look at [these other
+implementations](doc/other_implementations.md).
+
+Want to know more about the upcoming standard? Have a look at our
+[overview](doc/standards_effort.md).
+
+Most modern high-level languages provide ways to express sum types directly.
+If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums.
+
+## Depends
+
+- Compiler supporting `-std=c++11` or `-std=c++14`
+
+Tested with:
+
+- g++-4.7
+- g++-4.8
+- g++-4.9
+- g++-5.2
+- clang++-3.5
+- clang++-3.6
+- clang++-3.7
+- clang++-3.8
+- clang++-3.9
+- Visual Studio 2015
+
+## Unit Tests
+
+On Unix systems compile and run the unit tests with `make test`.
+
+On Windows run `scripts/build-local.bat`.
+
+## Limitations
+
+- The `variant` can not hold references (something like `variant<int&>` is
+ not possible). You might want to try `std::reference_wrapper` instead.
+
+## Deprecations
+
+- The included implementation of `optional` is deprecated and will be removed
+ in a future version. See [issue #64](https://github.com/mapbox/variant/issues/64).
+- Old versions of the code needed visitors to derive from `static_visitor`.
+ This is not needed any more and marked as deprecated. The `static_visitor`
+ class will be removed in future versions.
+
+## Benchmarks
+
+ make bench
+
+## Check object sizes
+
+ make sizes /path/to/boost/variant.hpp
diff --git a/third-party/mapbox/optional.hpp b/third-party/mapbox/optional.hpp
new file mode 100644
index 0000000000..d84705c1ac
--- /dev/null
+++ b/third-party/mapbox/optional.hpp
@@ -0,0 +1,74 @@
+#ifndef MAPBOX_UTIL_OPTIONAL_HPP
+#define MAPBOX_UTIL_OPTIONAL_HPP
+
+#pragma message("This implementation of optional is deprecated. See https://github.com/mapbox/variant/issues/64.")
+
+#include <type_traits>
+#include <utility>
+
+#include <mapbox/variant.hpp>
+
+namespace mapbox {
+namespace util {
+
+template <typename T>
+class optional
+{
+ static_assert(!std::is_reference<T>::value, "optional doesn't support references");
+
+ struct none_type
+ {
+ };
+
+ variant<none_type, T> variant_;
+
+public:
+ optional() = default;
+
+ optional(optional const& rhs)
+ {
+ if (this != &rhs)
+ { // protect against invalid self-assignment
+ variant_ = rhs.variant_;
+ }
+ }
+
+ optional(T const& v) { variant_ = v; }
+
+ explicit operator bool() const noexcept { return variant_.template is<T>(); }
+
+ T const& get() const { return variant_.template get<T>(); }
+ T& get() { return variant_.template get<T>(); }
+
+ T const& operator*() const { return this->get(); }
+ T operator*() { return this->get(); }
+
+ optional& operator=(T const& v)
+ {
+ variant_ = v;
+ return *this;
+ }
+
+ optional& operator=(optional const& rhs)
+ {
+ if (this != &rhs)
+ {
+ variant_ = rhs.variant_;
+ }
+ return *this;
+ }
+
+ template <typename... Args>
+ void emplace(Args&&... args)
+ {
+ variant_ = T{std::forward<Args>(args)...};
+ }
+
+ void reset() { variant_ = none_type{}; }
+
+}; // class optional
+
+} // namespace util
+} // namespace mapbox
+
+#endif // MAPBOX_UTIL_OPTIONAL_HPP
diff --git a/third-party/mapbox/recursive_wrapper.hpp b/third-party/mapbox/recursive_wrapper.hpp
new file mode 100644
index 0000000000..4ffcbd7c93
--- /dev/null
+++ b/third-party/mapbox/recursive_wrapper.hpp
@@ -0,0 +1,122 @@
+#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
+#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
+
+// Based on variant/recursive_wrapper.hpp from boost.
+//
+// Original license:
+//
+// Copyright (c) 2002-2003
+// Eric Friedman, Itay Maman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cassert>
+#include <utility>
+
+namespace mapbox {
+namespace util {
+
+template <typename T>
+class recursive_wrapper
+{
+
+ T* p_;
+
+ void assign(T const& rhs)
+ {
+ this->get() = rhs;
+ }
+
+public:
+ using type = T;
+
+ /**
+ * Default constructor default initializes the internally stored value.
+ * For POD types this means nothing is done and the storage is
+ * uninitialized.
+ *
+ * @throws std::bad_alloc if there is insufficient memory for an object
+ * of type T.
+ * @throws any exception thrown by the default constructur of T.
+ */
+ recursive_wrapper()
+ : p_(new T){}
+
+ ~recursive_wrapper() noexcept { delete p_; }
+
+ recursive_wrapper(recursive_wrapper const& operand)
+ : p_(new T(operand.get())) {}
+
+ recursive_wrapper(T const& operand)
+ : p_(new T(operand)) {}
+
+ recursive_wrapper(recursive_wrapper&& operand)
+ : p_(new T(std::move(operand.get()))) {}
+
+ recursive_wrapper(T&& operand)
+ : p_(new T(std::move(operand))) {}
+
+ inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
+ {
+ assign(rhs.get());
+ return *this;
+ }
+
+ inline recursive_wrapper& operator=(T const& rhs)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ inline void swap(recursive_wrapper& operand) noexcept
+ {
+ T* temp = operand.p_;
+ operand.p_ = p_;
+ p_ = temp;
+ }
+
+ recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
+ {
+ swap(rhs);
+ return *this;
+ }
+
+ recursive_wrapper& operator=(T&& rhs)
+ {
+ get() = std::move(rhs);
+ return *this;
+ }
+
+ T& get()
+ {
+ assert(p_);
+ return *get_pointer();
+ }
+
+ T const& get() const
+ {
+ assert(p_);
+ return *get_pointer();
+ }
+
+ T* get_pointer() { return p_; }
+
+ const T* get_pointer() const { return p_; }
+
+ operator T const&() const { return this->get(); }
+
+ operator T&() { return this->get(); }
+
+}; // class recursive_wrapper
+
+template <typename T>
+inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+} // namespace util
+} // namespace mapbox
+
+#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
diff --git a/third-party/mapbox/variant.hpp b/third-party/mapbox/variant.hpp
new file mode 100644
index 0000000000..06a46abe5d
--- /dev/null
+++ b/third-party/mapbox/variant.hpp
@@ -0,0 +1,1053 @@
+#ifndef MAPBOX_UTIL_VARIANT_HPP
+#define MAPBOX_UTIL_VARIANT_HPP
+
+#include <cassert>
+#include <cstddef> // size_t
+#include <new> // operator new
+#include <stdexcept> // runtime_error
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+#include <functional>
+#include <limits>
+
+#include <mapbox/recursive_wrapper.hpp>
+#include <mapbox/variant_visitor.hpp>
+
+// clang-format off
+// [[deprecated]] is only available in C++14, use this for the time being
+#if __cplusplus <= 201103L
+# ifdef __GNUC__
+# define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated))
+# elif defined(_MSC_VER)
+# define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated)
+# else
+# define MAPBOX_VARIANT_DEPRECATED
+# endif
+#else
+# define MAPBOX_VARIANT_DEPRECATED [[deprecated]]
+#endif
+
+
+#ifdef _MSC_VER
+// https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
+# ifdef NDEBUG
+# define VARIANT_INLINE __forceinline
+# else
+# define VARIANT_INLINE //__declspec(noinline)
+# endif
+#else
+# ifdef NDEBUG
+# define VARIANT_INLINE //inline __attribute__((always_inline))
+# else
+# define VARIANT_INLINE __attribute__((noinline))
+# endif
+#endif
+// clang-format on
+
+// Exceptions
+#if defined( __EXCEPTIONS) || defined( _MSC_VER)
+#define HAS_EXCEPTIONS
+#endif
+
+#define VARIANT_MAJOR_VERSION 1
+#define VARIANT_MINOR_VERSION 1
+#define VARIANT_PATCH_VERSION 0
+
+#define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
+
+namespace mapbox {
+namespace util {
+
+// XXX This should derive from std::logic_error instead of std::runtime_error.
+// See https://github.com/mapbox/variant/issues/48 for details.
+class bad_variant_access : public std::runtime_error
+{
+
+public:
+ explicit bad_variant_access(const std::string& what_arg)
+ : runtime_error(what_arg) {}
+
+ explicit bad_variant_access(const char* what_arg)
+ : runtime_error(what_arg) {}
+
+}; // class bad_variant_access
+
+#if !defined(MAPBOX_VARIANT_MINIMIZE_SIZE)
+using type_index_t = unsigned int;
+#else
+#if defined(MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED)
+using type_index_t = std::uint_fast8_t;
+#else
+using type_index_t = std::uint_least8_t;
+#endif
+#endif
+
+namespace detail {
+
+static constexpr type_index_t invalid_value = type_index_t(-1);
+
+template <typename T, typename... Types>
+struct direct_type;
+
+template <typename T, typename First, typename... Types>
+struct direct_type<T, First, Types...>
+{
+ static constexpr type_index_t index = std::is_same<T, First>::value
+ ? sizeof...(Types)
+ : direct_type<T, Types...>::index;
+};
+
+template <typename T>
+struct direct_type<T>
+{
+ static constexpr type_index_t index = invalid_value;
+};
+
+#if __cpp_lib_logical_traits >= 201510L
+
+using std::conjunction;
+using std::disjunction;
+
+#else
+
+template <typename...>
+struct conjunction : std::true_type {};
+
+template <typename B1>
+struct conjunction<B1> : B1 {};
+
+template <typename B1, typename B2>
+struct conjunction<B1, B2> : std::conditional<B1::value, B2, B1>::type {};
+
+template <typename B1, typename... Bs>
+struct conjunction<B1, Bs...> : std::conditional<B1::value, conjunction<Bs...>, B1>::type {};
+
+template <typename...>
+struct disjunction : std::false_type {};
+
+template <typename B1>
+struct disjunction<B1> : B1 {};
+
+template <typename B1, typename B2>
+struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
+
+template <typename B1, typename... Bs>
+struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
+
+#endif
+
+template <typename T, typename... Types>
+struct convertible_type;
+
+template <typename T, typename First, typename... Types>
+struct convertible_type<T, First, Types...>
+{
+ static constexpr type_index_t index = std::is_convertible<T, First>::value
+ ? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
+ : convertible_type<T, Types...>::index;
+};
+
+template <typename T>
+struct convertible_type<T>
+{
+ static constexpr type_index_t index = invalid_value;
+};
+
+template <typename T, typename... Types>
+struct value_traits
+{
+ using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
+ using value_type_wrapper = recursive_wrapper<value_type>;
+ static constexpr type_index_t direct_index = direct_type<value_type, Types...>::index;
+ static constexpr bool is_direct = direct_index != invalid_value;
+ static constexpr type_index_t index_direct_or_wrapper = is_direct ? direct_index : direct_type<value_type_wrapper, Types...>::index;
+ static constexpr bool is_direct_or_wrapper = index_direct_or_wrapper != invalid_value;
+ static constexpr type_index_t index = is_direct_or_wrapper ? index_direct_or_wrapper : convertible_type<value_type, Types...>::index;
+ static constexpr bool is_valid = index != invalid_value;
+ static constexpr type_index_t tindex = is_valid ? sizeof...(Types)-index : 0;
+ using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
+};
+
+template <typename Src, typename Dest>
+struct copy_cvref
+{
+ using type = Dest;
+};
+
+template <typename Src, typename Dest>
+struct copy_cvref<Src const&, Dest>
+{
+ using type = Dest const&;
+};
+
+template <typename Src, typename Dest>
+struct copy_cvref<Src&, Dest>
+{
+ using type = Dest&;
+};
+
+template <typename Src, typename Dest>
+struct copy_cvref<Src&&, Dest>
+{
+ using type = Dest&&;
+};
+
+template <typename F, typename = void>
+struct deduced_result_type
+{};
+
+template <typename F, typename... Args>
+struct deduced_result_type<F(Args...), decltype((void)std::declval<F>()(std::declval<Args>()...))>
+{
+ using type = decltype(std::declval<F>()(std::declval<Args>()...));
+};
+
+template <typename F, typename = void>
+struct visitor_result_type : deduced_result_type<F>
+{};
+
+// specialization for explicit result_type member in visitor class
+template <typename F, typename... Args>
+struct visitor_result_type<F(Args...), decltype((void)std::declval<typename std::decay<F>::type::result_type>())>
+{
+ using type = typename std::decay<F>::type::result_type;
+};
+
+template <typename F, typename T>
+using result_of_unary_visit = typename visitor_result_type<F&&(T&&)>::type;
+
+template <typename F, typename T>
+using result_of_binary_visit = typename visitor_result_type<F&&(T&&, T&&)>::type;
+
+template <type_index_t arg1, type_index_t... others>
+struct static_max;
+
+template <type_index_t arg>
+struct static_max<arg>
+{
+ static const type_index_t value = arg;
+};
+
+template <type_index_t arg1, type_index_t arg2, type_index_t... others>
+struct static_max<arg1, arg2, others...>
+{
+ static const type_index_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
+};
+
+template <typename... Types>
+struct variant_helper;
+
+template <typename T, typename... Types>
+struct variant_helper<T, Types...>
+{
+ VARIANT_INLINE static void destroy(const type_index_t type_index, void* data)
+ {
+ if (type_index == sizeof...(Types))
+ {
+ reinterpret_cast<T*>(data)->~T();
+ }
+ else
+ {
+ variant_helper<Types...>::destroy(type_index, data);
+ }
+ }
+
+ VARIANT_INLINE static void move(const type_index_t old_type_index, void* old_value, void* new_value)
+ {
+ if (old_type_index == sizeof...(Types))
+ {
+ new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
+ }
+ else
+ {
+ variant_helper<Types...>::move(old_type_index, old_value, new_value);
+ }
+ }
+
+ VARIANT_INLINE static void copy(const type_index_t old_type_index, const void* old_value, void* new_value)
+ {
+ if (old_type_index == sizeof...(Types))
+ {
+ new (new_value) T(*reinterpret_cast<const T*>(old_value));
+ }
+ else
+ {
+ variant_helper<Types...>::copy(old_type_index, old_value, new_value);
+ }
+ }
+};
+
+template <>
+struct variant_helper<>
+{
+ VARIANT_INLINE static void destroy(const type_index_t, void*) {}
+ VARIANT_INLINE static void move(const type_index_t, void*, void*) {}
+ VARIANT_INLINE static void copy(const type_index_t, const void*, void*) {}
+};
+
+template <typename T>
+struct unwrapper
+{
+ using value_type = T;
+
+ template <typename V>
+ static auto apply(typename std::remove_reference<V>::type& var)
+ -> typename std::enable_if<std::is_lvalue_reference<V>::value,
+ decltype(var.template get_unchecked<T>())>::type
+ {
+ return var.template get_unchecked<T>();
+ }
+
+ template <typename V>
+ static auto apply(typename std::remove_reference<V>::type& var)
+ -> typename std::enable_if<!std::is_lvalue_reference<V>::value,
+ decltype(std::move(var.template get_unchecked<T>()))>::type
+ {
+ return std::move(var.template get_unchecked<T>());
+ }
+};
+
+template <typename T>
+struct unwrapper<recursive_wrapper<T>> : unwrapper<T>
+{};
+
+template <typename T>
+struct unwrapper<std::reference_wrapper<T>> : unwrapper<T>
+{};
+
+template <typename R, typename... Types>
+struct dispatcher;
+
+template <typename R, typename T, typename... Types>
+struct dispatcher<R, T, Types...>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& v, F&& f)
+ {
+ if (v.template is<T>())
+ {
+ return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
+ }
+ else
+ {
+ return dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
+ }
+ }
+};
+
+template <typename R, typename T>
+struct dispatcher<R, T>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& v, F&& f)
+ {
+ return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
+ }
+};
+
+template <typename R, typename T, typename... Types>
+struct binary_dispatcher_rhs;
+
+template <typename R, typename T0, typename T1, typename... Types>
+struct binary_dispatcher_rhs<R, T0, T1, Types...>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
+ {
+ if (rhs.template is<T1>()) // call binary functor
+ {
+ return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
+ unwrapper<T1>::template apply<V>(rhs));
+ }
+ else
+ {
+ return binary_dispatcher_rhs<R, T0, Types...>::apply(std::forward<V>(lhs),
+ std::forward<V>(rhs),
+ std::forward<F>(f));
+ }
+ }
+};
+
+template <typename R, typename T0, typename T1>
+struct binary_dispatcher_rhs<R, T0, T1>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
+ {
+ return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
+ unwrapper<T1>::template apply<V>(rhs));
+ }
+};
+
+template <typename R, typename T, typename... Types>
+struct binary_dispatcher_lhs;
+
+template <typename R, typename T0, typename T1, typename... Types>
+struct binary_dispatcher_lhs<R, T0, T1, Types...>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
+ {
+ if (lhs.template is<T1>()) // call binary functor
+ {
+ return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
+ unwrapper<T0>::template apply<V>(rhs));
+ }
+ else
+ {
+ return binary_dispatcher_lhs<R, T0, Types...>::apply(std::forward<V>(lhs),
+ std::forward<V>(rhs),
+ std::forward<F>(f));
+ }
+ }
+};
+
+template <typename R, typename T0, typename T1>
+struct binary_dispatcher_lhs<R, T0, T1>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
+ {
+ return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
+ unwrapper<T0>::template apply<V>(rhs));
+ }
+};
+
+template <typename R, typename... Types>
+struct binary_dispatcher;
+
+template <typename R, typename T, typename... Types>
+struct binary_dispatcher<R, T, Types...>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
+ {
+ if (v0.template is<T>())
+ {
+ if (v1.template is<T>())
+ {
+ return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
+ unwrapper<T>::template apply<V>(v1)); // call binary functor
+ }
+ else
+ {
+ return binary_dispatcher_rhs<R, T, Types...>::apply(std::forward<V>(v0),
+ std::forward<V>(v1),
+ std::forward<F>(f));
+ }
+ }
+ else if (v1.template is<T>())
+ {
+ return binary_dispatcher_lhs<R, T, Types...>::apply(std::forward<V>(v0),
+ std::forward<V>(v1),
+ std::forward<F>(f));
+ }
+ return binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
+ std::forward<V>(v1),
+ std::forward<F>(f));
+ }
+};
+
+template <typename R, typename T>
+struct binary_dispatcher<R, T>
+{
+ template <typename V, typename F>
+ VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
+ {
+ return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
+ unwrapper<T>::template apply<V>(v1)); // call binary functor
+ }
+};
+
+// comparator functors
+struct equal_comp
+{
+ template <typename T>
+ bool operator()(T const& lhs, T const& rhs) const
+ {
+ return lhs == rhs;
+ }
+};
+
+struct less_comp
+{
+ template <typename T>
+ bool operator()(T const& lhs, T const& rhs) const
+ {
+ return lhs < rhs;
+ }
+};
+
+template <typename Variant, typename Comp>
+class comparer
+{
+public:
+ explicit comparer(Variant const& lhs) noexcept
+ : lhs_(lhs) {}
+ comparer& operator=(comparer const&) = delete;
+ // visitor
+ template <typename T>
+ bool operator()(T const& rhs_content) const
+ {
+ T const& lhs_content = lhs_.template get_unchecked<T>();
+ return Comp()(lhs_content, rhs_content);
+ }
+
+private:
+ Variant const& lhs_;
+};
+
+// hashing visitor
+struct hasher
+{
+ template <typename T>
+ std::size_t operator()(const T& hashable) const
+ {
+ return std::hash<T>{}(hashable);
+ }
+};
+
+} // namespace detail
+
+struct no_init {};
+
+template <typename... Types>
+class variant
+{
+ static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty.");
+ static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
+ static_assert(!detail::disjunction<std::is_array<Types>...>::value, "Variant can not hold array types.");
+ static_assert(sizeof...(Types) < std::numeric_limits<type_index_t>::max(), "Internal index type must be able to accommodate all alternatives.");
+private:
+ static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
+ static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
+public:
+ struct adapted_variant_tag;
+ using types = std::tuple<Types...>;
+private:
+ using first_type = typename std::tuple_element<0, types>::type;
+ using unwrap_first_type = typename detail::unwrapper<first_type>::value_type;
+ using data_type = typename std::aligned_storage<data_size, data_align>::type;
+ using helper_type = detail::variant_helper<Types...>;
+
+ template <typename V, typename T = unwrap_first_type>
+ using alternative_ref = typename detail::copy_cvref<V, T>::type;
+
+ type_index_t type_index;
+#ifdef __clang_analyzer__
+ data_type data {};
+#else
+ data_type data;
+#endif
+
+public:
+ VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
+ : type_index(sizeof...(Types)-1)
+ {
+ static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant.");
+ new (&data) first_type();
+ }
+
+ VARIANT_INLINE variant(no_init) noexcept
+ : type_index(detail::invalid_value) {}
+
+ // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
+ template <typename T, typename Traits = detail::value_traits<T, Types...>,
+ typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
+ VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
+ : type_index(Traits::index)
+ {
+ new (&data) typename Traits::target_type(std::forward<T>(val));
+ }
+
+ VARIANT_INLINE variant(variant<Types...> const& old)
+ : type_index(old.type_index)
+ {
+ helper_type::copy(old.type_index, &old.data, &data);
+ }
+
+ VARIANT_INLINE variant(variant<Types...>&& old)
+ noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
+ : type_index(old.type_index)
+ {
+ helper_type::move(old.type_index, &old.data, &data);
+ }
+
+private:
+ VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
+ {
+ helper_type::destroy(type_index, &data);
+ type_index = detail::invalid_value;
+ helper_type::copy(rhs.type_index, &rhs.data, &data);
+ type_index = rhs.type_index;
+ }
+
+ VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
+ {
+ helper_type::destroy(type_index, &data);
+ type_index = detail::invalid_value;
+ helper_type::move(rhs.type_index, &rhs.data, &data);
+ type_index = rhs.type_index;
+ }
+
+public:
+ VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
+ // note we check for nothrow-constructible, not nothrow-assignable, since
+ // move_assign uses move-construction via placement new.
+ noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
+ {
+ if (this == &other) { // playing safe in release mode, hit assertion in debug.
+ assert(false);
+ return *this;
+ }
+ move_assign(std::move(other));
+ return *this;
+ }
+
+ VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
+ {
+ if (this != &other)
+ copy_assign(other);
+ return *this;
+ }
+
+ // conversions
+ // move-assign
+ template <typename T, typename Traits = detail::value_traits<T, Types...>,
+ typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
+ VARIANT_INLINE variant<Types...>& operator=(T&& rhs)
+ // not that we check is_nothrow_constructible<T>, not is_nothrow_move_assignable<T>,
+ // since we construct a temporary
+ noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value
+ && std::is_nothrow_move_assignable<variant<Types...>>::value)
+ {
+ variant<Types...> temp(std::forward<T>(rhs));
+ move_assign(std::move(temp));
+ return *this;
+ }
+
+ // copy-assign
+ template <typename T>
+ VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
+ {
+ variant<Types...> temp(rhs);
+ copy_assign(temp);
+ return *this;
+ }
+
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE bool is() const
+ {
+ return type_index == detail::direct_type<T, Types...>::index;
+ }
+
+ template <typename T,typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE bool is() const
+ {
+ return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
+ }
+
+ VARIANT_INLINE bool valid() const
+ {
+ return type_index != detail::invalid_value;
+ }
+
+ template <typename T, typename... Args>
+ VARIANT_INLINE void set(Args&&... args)
+ {
+ helper_type::destroy(type_index, &data);
+ type_index = detail::invalid_value;
+ new (&data) T(std::forward<Args>(args)...);
+ type_index = detail::direct_type<T, Types...>::index;
+ }
+
+ // get_unchecked<T>()
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get_unchecked()
+ {
+ return *reinterpret_cast<T*>(&data);
+ }
+
+#ifdef HAS_EXCEPTIONS
+ // get<T>()
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get()
+ {
+ if (type_index == detail::direct_type<T, Types...>::index)
+ {
+ return *reinterpret_cast<T*>(&data);
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get_unchecked() const
+ {
+ return *reinterpret_cast<T const*>(&data);
+ }
+
+#ifdef HAS_EXCEPTIONS
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get() const
+ {
+ if (type_index == detail::direct_type<T, Types...>::index)
+ {
+ return *reinterpret_cast<T const*>(&data);
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ // get_unchecked<T>() - T stored as recursive_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get_unchecked()
+ {
+ return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
+ }
+
+#ifdef HAS_EXCEPTIONS
+ // get<T>() - T stored as recursive_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get()
+ {
+ if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get_unchecked() const
+ {
+ return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
+ }
+
+#ifdef HAS_EXCEPTIONS
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get() const
+ {
+ if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ // get_unchecked<T>() - T stored as std::reference_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get_unchecked()
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
+ }
+
+#ifdef HAS_EXCEPTIONS
+ // get<T>() - T stored as std::reference_wrapper<T>
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T& get()
+ {
+ if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get_unchecked() const
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
+ }
+
+#ifdef HAS_EXCEPTIONS
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE T const& get() const
+ {
+ if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
+ {
+ return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
+ }
+ else
+ {
+ throw bad_variant_access("in get<T>()");
+ }
+ }
+#endif
+
+ // This function is deprecated because it returns an internal index field.
+ // Use which() instead.
+ MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE type_index_t get_type_index() const
+ {
+ return type_index;
+ }
+
+ VARIANT_INLINE int which() const noexcept
+ {
+ return static_cast<int>(sizeof...(Types) - type_index - 1);
+ }
+
+ template <typename T, typename std::enable_if<
+ (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
+ VARIANT_INLINE static constexpr int which() noexcept
+ {
+ return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
+ }
+
+ // visitor
+ // unary
+ template <typename F, typename V, typename T0 = alternative_ref<V>,
+ typename R = detail::result_of_unary_visit<F, T0>>
+ VARIANT_INLINE static R visit(V&& v, F&& f)
+ {
+ return detail::dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
+ }
+
+ // binary
+ template <typename F, typename V, typename T0 = alternative_ref<V>,
+ typename R = detail::result_of_binary_visit<F, T0>>
+ VARIANT_INLINE static R binary_visit(V&& v0, V&& v1, F&& f)
+ {
+ return detail::binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
+ std::forward<V>(v1),
+ std::forward<F>(f));
+ }
+
+ // match
+ // unary
+ template <typename... Fs>
+ auto VARIANT_INLINE match(Fs&&... fs) const&
+ -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
+ {
+ return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
+ }
+ // non-const
+ template <typename... Fs>
+ auto VARIANT_INLINE match(Fs&&... fs) &
+ -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
+ {
+ return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
+ }
+ template <typename... Fs>
+ auto VARIANT_INLINE match(Fs&&... fs) &&
+ -> decltype(variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
+ {
+ return variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
+ }
+
+ ~variant() noexcept // no-throw destructor
+ {
+ helper_type::destroy(type_index, &data);
+ }
+
+ // comparison operators
+ // equality
+ VARIANT_INLINE bool operator==(variant const& rhs) const
+ {
+ assert(valid() && rhs.valid());
+ if (this->which() != rhs.which())
+ {
+ return false;
+ }
+ detail::comparer<variant, detail::equal_comp> visitor(*this);
+ return visit(rhs, visitor);
+ }
+
+ VARIANT_INLINE bool operator!=(variant const& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ // less than
+ VARIANT_INLINE bool operator<(variant const& rhs) const
+ {
+ assert(valid() && rhs.valid());
+ if (this->which() != rhs.which())
+ {
+ return this->which() < rhs.which();
+ }
+ detail::comparer<variant, detail::less_comp> visitor(*this);
+ return visit(rhs, visitor);
+ }
+ VARIANT_INLINE bool operator>(variant const& rhs) const
+ {
+ return rhs < *this;
+ }
+ VARIANT_INLINE bool operator<=(variant const& rhs) const
+ {
+ return !(*this > rhs);
+ }
+ VARIANT_INLINE bool operator>=(variant const& rhs) const
+ {
+ return !(*this < rhs);
+ }
+};
+
+// unary visitor interface
+template <typename F, typename V>
+auto VARIANT_INLINE apply_visitor(F&& f, V&& v)
+ -> decltype(v.visit(std::forward<V>(v), std::forward<F>(f)))
+{
+ return v.visit(std::forward<V>(v), std::forward<F>(f));
+}
+
+// binary visitor interface
+template <typename F, typename V>
+auto VARIANT_INLINE apply_visitor(F&& f, V&& v0, V&& v1)
+ -> decltype(v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f)))
+{
+ return v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f));
+}
+
+// getter interface
+
+#ifdef HAS_EXCEPTIONS
+template <typename ResultType, typename T>
+auto get(T& var)->decltype(var.template get<ResultType>())
+{
+ return var.template get<ResultType>();
+}
+#endif
+
+template <typename ResultType, typename T>
+ResultType& get_unchecked(T& var)
+{
+ return var.template get_unchecked<ResultType>();
+}
+
+#ifdef HAS_EXCEPTIONS
+template <typename ResultType, typename T>
+auto get(T const& var)->decltype(var.template get<ResultType>())
+{
+ return var.template get<ResultType>();
+}
+#endif
+
+template <typename ResultType, typename T>
+ResultType const& get_unchecked(T const& var)
+{
+ return var.template get_unchecked<ResultType>();
+}
+// variant_size
+template <typename T>
+struct variant_size;
+
+//variable templates is c++14
+//template <typename T>
+//constexpr std::size_t variant_size_v = variant_size<T>::value;
+
+template <typename T>
+struct variant_size<const T>
+ : variant_size<T> {};
+
+template <typename T>
+struct variant_size<volatile T>
+ : variant_size<T> {};
+
+template <typename T>
+struct variant_size<const volatile T>
+ : variant_size<T> {};
+
+template <typename... Types>
+struct variant_size<variant<Types...>>
+ : std::integral_constant<std::size_t, sizeof...(Types)> {};
+
+// variant_alternative
+template <std::size_t Index, typename T>
+struct variant_alternative;
+
+#if defined(__clang__)
+#if __has_builtin(__type_pack_element)
+#define has_type_pack_element
+#endif
+#endif
+
+#if defined(has_type_pack_element)
+template <std::size_t Index, typename ...Types>
+struct variant_alternative<Index, variant<Types...>>
+{
+ static_assert(sizeof...(Types) > Index , "Index out of range");
+ using type = __type_pack_element<Index, Types...>;
+};
+#else
+template <std::size_t Index, typename First, typename...Types>
+struct variant_alternative<Index, variant<First, Types...>>
+ : variant_alternative<Index - 1, variant<Types...>>
+{
+ static_assert(sizeof...(Types) > Index -1 , "Index out of range");
+};
+
+template <typename First, typename...Types>
+struct variant_alternative<0, variant<First, Types...>>
+{
+ using type = First;
+};
+
+#endif
+
+template <size_t Index, typename T>
+using variant_alternative_t = typename variant_alternative<Index, T>::type;
+
+template <size_t Index, typename T>
+struct variant_alternative<Index, const T>
+ : std::add_const<variant_alternative<Index, T>> {};
+
+template <size_t Index, typename T>
+struct variant_alternative<Index, volatile T>
+ : std::add_volatile<variant_alternative<Index, T>> {};
+
+template <size_t Index, typename T>
+struct variant_alternative<Index, const volatile T>
+ : std::add_cv<variant_alternative<Index, T>> {};
+
+} // namespace util
+} // namespace mapbox
+
+// hashable iff underlying types are hashable
+namespace std {
+template <typename... Types>
+struct hash< ::mapbox::util::variant<Types...>> {
+ std::size_t operator()(const ::mapbox::util::variant<Types...>& v) const noexcept
+ {
+ return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
+ }
+};
+
+}
+
+#endif // MAPBOX_UTIL_VARIANT_HPP
diff --git a/third-party/mapbox/variant_cast.hpp b/third-party/mapbox/variant_cast.hpp
new file mode 100644
index 0000000000..fe1ab35432
--- /dev/null
+++ b/third-party/mapbox/variant_cast.hpp
@@ -0,0 +1,85 @@
+#ifndef VARIANT_CAST_HPP
+#define VARIANT_CAST_HPP
+
+#include <type_traits>
+
+namespace mapbox {
+namespace util {
+
+namespace detail {
+
+template <class T>
+class static_caster
+{
+public:
+ template <class V>
+ T& operator()(V& v) const
+ {
+ return static_cast<T&>(v);
+ }
+};
+
+template <class T>
+class dynamic_caster
+{
+public:
+ using result_type = T&;
+ template <class V>
+ T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
+ {
+ throw std::bad_cast();
+ }
+ template <class V>
+ T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
+ {
+ return dynamic_cast<T&>(v);
+ }
+};
+
+template <class T>
+class dynamic_caster<T*>
+{
+public:
+ using result_type = T*;
+ template <class V>
+ T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
+ {
+ return nullptr;
+ }
+ template <class V>
+ T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
+ {
+ return dynamic_cast<T*>(&v);
+ }
+};
+}
+
+template <class T, class V>
+typename detail::dynamic_caster<T>::result_type
+dynamic_variant_cast(V& v)
+{
+ return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
+}
+
+template <class T, class V>
+typename detail::dynamic_caster<const T>::result_type
+dynamic_variant_cast(const V& v)
+{
+ return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
+}
+
+template <class T, class V>
+T& static_variant_cast(V& v)
+{
+ return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
+}
+
+template <class T, class V>
+const T& static_variant_cast(const V& v)
+{
+ return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
+}
+}
+}
+
+#endif // VARIANT_CAST_HPP
diff --git a/third-party/mapbox/variant_io.hpp b/third-party/mapbox/variant_io.hpp
new file mode 100644
index 0000000000..1456cc5abc
--- /dev/null
+++ b/third-party/mapbox/variant_io.hpp
@@ -0,0 +1,45 @@
+#ifndef MAPBOX_UTIL_VARIANT_IO_HPP
+#define MAPBOX_UTIL_VARIANT_IO_HPP
+
+#include <iosfwd>
+
+#include <mapbox/variant.hpp>
+
+namespace mapbox {
+namespace util {
+
+namespace detail {
+// operator<< helper
+template <typename Out>
+class printer
+{
+public:
+ explicit printer(Out& out)
+ : out_(out) {}
+ printer& operator=(printer const&) = delete;
+
+ // visitor
+ template <typename T>
+ void operator()(T const& operand) const
+ {
+ out_ << operand;
+ }
+
+private:
+ Out& out_;
+};
+}
+
+// operator<<
+template <typename CharT, typename Traits, typename... Types>
+VARIANT_INLINE std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& out, variant<Types...> const& rhs)
+{
+ detail::printer<std::basic_ostream<CharT, Traits>> visitor(out);
+ apply_visitor(visitor, rhs);
+ return out;
+}
+} // namespace util
+} // namespace mapbox
+
+#endif // MAPBOX_UTIL_VARIANT_IO_HPP
diff --git a/third-party/mapbox/variant_visitor.hpp b/third-party/mapbox/variant_visitor.hpp
new file mode 100644
index 0000000000..54ddba0e1c
--- /dev/null
+++ b/third-party/mapbox/variant_visitor.hpp
@@ -0,0 +1,43 @@
+#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
+#define MAPBOX_UTIL_VARIANT_VISITOR_HPP
+
+#include <utility>
+
+namespace mapbox {
+namespace util {
+
+template <typename... Fns>
+struct visitor;
+
+template <typename Fn>
+struct visitor<Fn> : Fn
+{
+ using Fn::operator();
+
+ template<typename T>
+ visitor(T&& fn) : Fn(std::forward<T>(fn)) {}
+};
+
+template <typename Fn, typename... Fns>
+struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
+{
+ using Fn::operator();
+ using visitor<Fns...>::operator();
+
+ template<typename T, typename... Ts>
+ visitor(T&& fn, Ts&&... fns)
+ : Fn(std::forward<T>(fn))
+ , visitor<Fns...>(std::forward<Ts>(fns)...) {}
+};
+
+template <typename... Fns>
+visitor<typename std::decay<Fns>::type...> make_visitor(Fns&&... fns)
+{
+ return visitor<typename std::decay<Fns>::type...>
+ (std::forward<Fns>(fns)...);
+}
+
+} // namespace util
+} // namespace mapbox
+
+#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP