From b46c102eb0ec3ca2ff0b422831cb98fa2bdebcba Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Wed, 30 Sep 2015 16:14:32 -0400 Subject: mason variant@1.0 --- include/mbgl/util/variant.hpp | 793 ------------------------------------------ 1 file changed, 793 deletions(-) delete mode 100644 include/mbgl/util/variant.hpp (limited to 'include/mbgl/util/variant.hpp') diff --git a/include/mbgl/util/variant.hpp b/include/mbgl/util/variant.hpp deleted file mode 100644 index a3cdea63a7..0000000000 --- a/include/mbgl/util/variant.hpp +++ /dev/null @@ -1,793 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_HPP -#define MAPBOX_UTIL_VARIANT_HPP - -#include -#include -#include -#include // runtime_error -#include // operator new -#include // size_t -#include -#include - -#include "recursive_wrapper.hpp" - -#ifdef _MSC_VER - // http://msdn.microsoft.com/en-us/library/z8y1yy88.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 - -#define VARIANT_MAJOR_VERSION 0 -#define VARIANT_MINOR_VERSION 1 -#define VARIANT_PATCH_VERSION 0 - -// translates to 100 -#define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) - -namespace mapbox { namespace util { - -// static visitor -template -struct static_visitor -{ - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} -}; - -namespace detail { - -static constexpr std::size_t invalid_value = std::size_t(-1); - -template -struct direct_type; - -template -struct direct_type -{ - static constexpr std::size_t index = std::is_same::value - ? sizeof...(Types) : direct_type::index; -}; - -template -struct direct_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct convertible_type; - -template -struct convertible_type -{ - static constexpr std::size_t index = std::is_convertible::value - ? sizeof...(Types) : convertible_type::index; -}; - -template -struct convertible_type -{ - static constexpr std::size_t index = invalid_value; -}; - -template -struct value_traits -{ - static constexpr std::size_t direct_index = direct_type::index; - static constexpr std::size_t index = - (direct_index == invalid_value) ? convertible_type::index : direct_index; -}; - -template -struct is_valid_type; - -template -struct is_valid_type -{ - static constexpr bool value = std::is_convertible::value - || is_valid_type::value; -}; - -template -struct is_valid_type : std::false_type {}; - -template -struct select_type -{ - static_assert(N < sizeof...(Types), "index out of bounds"); -}; - -template -struct select_type -{ - using type = typename select_type::type; -}; - -template -struct select_type<0, T, Types...> -{ - using type = T; -}; - - -template -struct enable_if_type { using type = R; }; - -template -struct result_of_unary_visit -{ - using type = typename std::result_of::type; -}; - -template -struct result_of_unary_visit::type > -{ - using type = typename F::result_type; -}; - -template -struct result_of_binary_visit -{ - using type = typename std::result_of::type; -}; - - -template -struct result_of_binary_visit::type > -{ - using type = typename F::result_type; -}; - - -} // namespace detail - - -template -struct static_max; - -template -struct static_max -{ - static const std::size_t value = arg; -}; - -template -struct static_max -{ - static const std::size_t value = arg1 >= arg2 ? static_max::value : - static_max::value; -}; - -template -struct variant_helper; - -template -struct variant_helper -{ - VARIANT_INLINE static void destroy(const std::size_t id, void * data) - { - if (id == sizeof...(Types)) - { - reinterpret_cast(data)->~T(); - } - else - { - variant_helper::destroy(id, data); - } - } - - VARIANT_INLINE static void move(const std::size_t old_id, void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(std::move(*reinterpret_cast(old_value))); - //std::memcpy(new_value, old_value, sizeof(T)); - // ^^ DANGER: this should only be considered for relocatable types e.g built-in types - // Also, I don't see any measurable performance benefit just yet - } - else - { - variant_helper::move(old_id, old_value, new_value); - } - } - - VARIANT_INLINE static void copy(const std::size_t old_id, const void * old_value, void * new_value) - { - if (old_id == sizeof...(Types)) - { - new (new_value) T(*reinterpret_cast(old_value)); - } - else - { - variant_helper::copy(old_id, old_value, new_value); - } - } -}; - -template<> struct variant_helper<> -{ - VARIANT_INLINE static void destroy(const std::size_t, void *) {} - VARIANT_INLINE static void move(const std::size_t, void *, void *) {} - VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} -}; - -namespace detail { - -template -struct unwrapper -{ - T const& operator() (T const& obj) const - { - return obj; - } - - T& operator() (T & obj) const - { - return obj; - } -}; - - -template -struct unwrapper> -{ - auto operator() (recursive_wrapper const& obj) const - -> typename recursive_wrapper::type const& - { - return obj.get(); - } -}; - - -template -struct dispatcher; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply_const(v, f); - } - } - - VARIANT_INLINE static result_type apply(V & v, F f) - { - if (v.get_type_index() == sizeof...(Types)) - { - return f(unwrapper()(v. template get())); - } - else - { - return dispatcher::apply(v, f); - } - } -}; - -template -struct dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } - - VARIANT_INLINE static result_type apply(V &, F) - { - throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); - } -}; - - -template -struct binary_dispatcher_rhs; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (rhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(unwrapper()(lhs. template get()), - unwrapper()(rhs. template get())); - } - else - { - return binary_dispatcher_rhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_rhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - - -template -struct binary_dispatcher_lhs; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply_const(lhs, rhs, f); - } - } - - VARIANT_INLINE static result_type apply(V & lhs, V & rhs, F f) - { - if (lhs.get_type_index() == sizeof...(Types)) // call binary functor - { - return f(lhs. template get(), rhs. template get()); - } - else - { - return binary_dispatcher_lhs::apply(lhs, rhs, f); - } - } - -}; - -template -struct binary_dispatcher_lhs -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -template -struct binary_dispatcher; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply_const(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply_const(v0, v1, f); - } - return binary_dispatcher::apply_const(v0, v1, f); - } - - VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) - { - if (v0.get_type_index() == sizeof...(Types)) - { - if (v0.get_type_index() == v1.get_type_index()) - { - return f(v0. template get(), v1. template get()); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply(v0, v1, f); - } - } - else if (v1.get_type_index() == sizeof...(Types)) - { - return binary_dispatcher_lhs::apply(v0, v1, f); - } - return binary_dispatcher::apply(v0, v1, f); - } -}; - -template -struct binary_dispatcher -{ - using result_type = R; - VARIANT_INLINE static result_type apply_const(V const&, V const&, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } - - VARIANT_INLINE static result_type apply(V &, V &, F) - { - throw std::runtime_error("binary dispatch: FAIL"); - } -}; - -// comparator functors -struct equal_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs == rhs; - } -}; - -struct less_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs < rhs; - } -}; - -template -class comparer -{ -public: - explicit comparer(Variant const& lhs) noexcept - : lhs_(lhs) {} - comparer& operator=(comparer const&) = delete; - // visitor - template - bool operator()(T const& rhs_content) const - { - T const& lhs_content = lhs_.template get(); - return Comp()(lhs_content, rhs_content); - } -private: - Variant const& lhs_; -}; - - -} // namespace detail - -struct no_init {}; - -template -class variant -{ -private: - - static const std::size_t data_size = static_max::value; - static const std::size_t data_align = static_max::value; - - using data_type = typename std::aligned_storage::type; - using helper_type = variant_helper; - - std::size_t type_index; - data_type data; - -public: - - VARIANT_INLINE variant() - : type_index(sizeof...(Types) - 1) - { - new (&data) typename detail::select_type<0, Types...>::type(); - } - - VARIANT_INLINE variant(no_init) - : type_index(detail::invalid_value) {} - - // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - template ::type, Types...>::value>::type> - VARIANT_INLINE variant(T && val) noexcept - : type_index(detail::value_traits::type, Types...>::index) - { - constexpr std::size_t index = sizeof...(Types) - detail::value_traits::type, Types...>::index - 1; - using target_type = typename detail::select_type::type; - new (&data) target_type(std::forward(val)); // nothrow - } - - VARIANT_INLINE variant(variant const& old) - : type_index(old.type_index) - { - helper_type::copy(old.type_index, &old.data, &data); - } - - VARIANT_INLINE variant(variant&& old) noexcept - : type_index(old.type_index) - { - helper_type::move(old.type_index, &old.data, &data); - } - - friend void swap(variant & first, variant & second) - { - using std::swap; //enable ADL - swap(first.type_index, second.type_index); - swap(first.data, second.data); - } - - VARIANT_INLINE variant& operator=(variant other) - { - swap(*this, other); - return *this; - } - - // conversions - // move-assign - template - VARIANT_INLINE variant& operator=(T && rhs) noexcept - { - variant temp(std::forward(rhs)); - swap(*this, temp); - return *this; - } - - // copy-assign - template - VARIANT_INLINE variant& operator=(T const& rhs) - { - variant temp(rhs); - swap(*this, temp); - return *this; - } - - template - VARIANT_INLINE bool is() const - { - return (type_index == detail::direct_type::index); - } - - VARIANT_INLINE bool valid() const - { - return (type_index != detail::invalid_value); - } - - template - VARIANT_INLINE void set(Args&&... args) - { - helper_type::destroy(type_index, &data); - new (&data) T(std::forward(args)...); - type_index = detail::direct_type::index; - } - - // get() - template::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template ::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw std::runtime_error("in get()"); - } - } - - // get() - T stored as recursive_wrapper - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - - template , Types...>::index != detail::invalid_value) - >::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast const*>(&data)).get(); - } - else - { - throw std::runtime_error("in get()"); - } - } - VARIANT_INLINE std::size_t get_type_index() const - { - return type_index; - } - - VARIANT_INLINE int which() const noexcept - { - return static_cast(sizeof...(Types) - type_index - 1); - } - - // visitor - // unary - template - auto VARIANT_INLINE - static visit(V const& v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply_const(v, f); - } - // non-const - template - auto VARIANT_INLINE - static visit(V & v, F f) - -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) - { - using R = typename detail::result_of_unary_visit::type>::type; - return detail::dispatcher::apply(v, f); - } - - // binary - // const - template - auto VARIANT_INLINE - static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply_const(v0, v1, f); - } - // non-const - template - auto VARIANT_INLINE - static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) - { - using R = typename detail::result_of_binary_visit::type>::type; - return detail::binary_dispatcher::apply(v0, v1, f); - } - - ~variant() noexcept - { - helper_type::destroy(type_index, &data); - } - - // comparison operators - // equality - VARIANT_INLINE bool operator==(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - return false; - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - // less than - VARIANT_INLINE bool operator<(variant const& rhs) const - { - if (this->get_type_index() != rhs.get_type_index()) - { - return this->get_type_index() < rhs.get_type_index(); - // ^^ borrowed from boost::variant - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } -}; - -// unary visitor interface - -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v) -> decltype(V::visit(v, f)) -{ - return V::visit(v, f); -} - -// binary visitor interface -// const -template -auto VARIANT_INLINE static apply_visitor(F f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} -// non-const -template -auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::binary_visit(v0, v1, f)) -{ - return V::binary_visit(v0, v1, f); -} - -// getter interface -template -ResultType & get(T & var) -{ - return var.template get(); -} - -template -ResultType const& get(T const& var) -{ - return var.template get(); -} - - -}} - -#endif // MAPBOX_UTIL_VARIANT_HPP -- cgit v1.2.1