diff options
Diffstat (limited to 'include/mbgl/util/variant.hpp')
-rw-r--r-- | include/mbgl/util/variant.hpp | 187 |
1 files changed, 104 insertions, 83 deletions
diff --git a/include/mbgl/util/variant.hpp b/include/mbgl/util/variant.hpp index 411f1918d5..a3cdea63a7 100644 --- a/include/mbgl/util/variant.hpp +++ b/include/mbgl/util/variant.hpp @@ -251,13 +251,13 @@ struct unwrapper<recursive_wrapper<T>> }; -template <typename F, typename V, typename...Types> +template <typename F, typename V, typename R, typename...Types> struct dispatcher; -template <typename F, typename V, typename T, typename...Types> -struct dispatcher<F, V, T, Types...> +template <typename F, typename V, typename R, typename T, typename...Types> +struct dispatcher<F, V, R, T, Types...> { - using result_type = typename detail::result_of_unary_visit<F, V>::type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const& v, F f) { if (v.get_type_index() == sizeof...(Types)) @@ -266,7 +266,7 @@ struct dispatcher<F, V, T, Types...> } else { - return dispatcher<F, V, Types...>::apply_const(v, f); + return dispatcher<F, V, R, Types...>::apply_const(v, f); } } @@ -278,15 +278,15 @@ struct dispatcher<F, V, T, Types...> } else { - return dispatcher<F, V, Types...>::apply(v, f); + return dispatcher<F, V, R, Types...>::apply(v, f); } } }; -template<typename F, typename V> -struct dispatcher<F, V> +template<typename F, typename V, typename R> +struct dispatcher<F, V, R> { - using result_type = typename detail::result_of_unary_visit<F, V>::type; + 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()); @@ -299,13 +299,13 @@ struct dispatcher<F, V> }; -template <typename F, typename V, typename T, typename...Types> +template <typename F, typename V, typename R, typename T, typename...Types> struct binary_dispatcher_rhs; -template <typename F, typename V, typename T0, typename T1, typename...Types> -struct binary_dispatcher_rhs<F, V, T0, T1, Types...> +template <typename F, typename V, typename R, typename T0, typename T1, typename...Types> +struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + 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 @@ -315,7 +315,7 @@ struct binary_dispatcher_rhs<F, V, T0, T1, Types...> } else { - return binary_dispatcher_rhs<F, V, T0, Types...>::apply_const(lhs, rhs, f); + return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, f); } } @@ -328,16 +328,16 @@ struct binary_dispatcher_rhs<F, V, T0, T1, Types...> } else { - return binary_dispatcher_rhs<F, V, T0, Types...>::apply(lhs, rhs, f); + return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, f); } } }; -template<typename F, typename V, typename T> -struct binary_dispatcher_rhs<F, V, T> +template<typename F, typename V, typename R, typename T> +struct binary_dispatcher_rhs<F, V, R, T> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -349,13 +349,13 @@ struct binary_dispatcher_rhs<F, V, T> }; -template <typename F, typename V, typename T, typename...Types> +template <typename F, typename V, typename R, typename T, typename...Types> struct binary_dispatcher_lhs; -template <typename F, typename V, typename T0, typename T1, typename...Types> -struct binary_dispatcher_lhs<F, V, T0, T1, Types...> +template <typename F, typename V, typename R, typename T0, typename T1, typename...Types> +struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + 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 @@ -364,7 +364,7 @@ struct binary_dispatcher_lhs<F, V, T0, T1, Types...> } else { - return binary_dispatcher_lhs<F, V, T0, Types...>::apply_const(lhs, rhs, f); + return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, f); } } @@ -376,16 +376,16 @@ struct binary_dispatcher_lhs<F, V, T0, T1, Types...> } else { - return binary_dispatcher_lhs<F, V, T0, Types...>::apply(lhs, rhs, f); + return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, f); } } }; -template<typename F, typename V, typename T> -struct binary_dispatcher_lhs<F, V, T> +template<typename F, typename V, typename R, typename T> +struct binary_dispatcher_lhs<F, V, R, T> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -397,13 +397,13 @@ struct binary_dispatcher_lhs<F, V, T> } }; -template <typename F, typename V, typename...Types> +template <typename F, typename V, typename R, typename...Types> struct binary_dispatcher; -template <typename F, typename V, typename T, typename...Types> -struct binary_dispatcher<F, V, T, Types...> +template <typename F, typename V, typename R, typename T, typename...Types> +struct binary_dispatcher<F, V, R, T, Types...> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + 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)) @@ -414,14 +414,14 @@ struct binary_dispatcher<F, V, T, Types...> } else { - return binary_dispatcher_rhs<F, V, T, Types...>::apply_const(v0, v1, f); + return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, f); } } else if (v1.get_type_index() == sizeof...(Types)) { - return binary_dispatcher_lhs<F, V, T, Types...>::apply_const(v0, v1, f); + return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, f); } - return binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f); + return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, f); } VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) @@ -434,21 +434,21 @@ struct binary_dispatcher<F, V, T, Types...> } else { - return binary_dispatcher_rhs<F, V, T, Types...>::apply(v0, v1, f); + return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, f); } } else if (v1.get_type_index() == sizeof...(Types)) { - return binary_dispatcher_lhs<F, V, T, Types...>::apply(v0, v1, f); + return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, f); } - return binary_dispatcher<F, V, Types...>::apply(v0, v1, f); + return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, f); } }; -template<typename F, typename V> -struct binary_dispatcher<F, V> +template<typename F, typename V, typename R> +struct binary_dispatcher<F, V, R> { - using result_type = typename detail::result_of_binary_visit<F, V>::type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -497,24 +497,6 @@ private: Variant const& lhs_; }; -// 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_; -}; } // namespace detail @@ -536,7 +518,6 @@ private: public: - VARIANT_INLINE variant() : type_index(sizeof...(Types) - 1) { @@ -620,7 +601,8 @@ public: type_index = detail::direct_type<T, Types...>::index; } - template<typename T> + // 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) @@ -629,11 +611,13 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get<T>()"); } } - template<typename T> + 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) @@ -642,31 +626,72 @@ public: } else { - throw std::runtime_error("in get()"); + throw std::runtime_error("in get<T>()"); + } + } + + // 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 std::runtime_error("in get<T>()"); } } + 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 std::runtime_error("in get<T>()"); + } + } VARIANT_INLINE std::size_t get_type_index() const { return type_index; } + VARIANT_INLINE int which() const noexcept + { + return static_cast<int>(sizeof...(Types) - type_index - 1); + } + // visitor // unary template <typename F, typename V> auto VARIANT_INLINE static visit(V const& v, F f) - -> decltype(detail::dispatcher<F, V, Types...>::apply_const(v, f)) + -> decltype(detail::dispatcher<F, V, + typename detail::result_of_unary_visit<F, + typename detail::select_type<0, Types...>::type>::type, Types...>::apply_const(v, f)) { - return detail::dispatcher<F, V, Types...>::apply_const(v, f); + using R = typename detail::result_of_unary_visit<F, typename detail::select_type<0, Types...>::type>::type; + return detail::dispatcher<F, V, R, Types...>::apply_const(v, f); } // non-const template <typename F, typename V> auto VARIANT_INLINE static visit(V & v, F f) - -> decltype(detail::dispatcher<F, V, Types...>::apply(v, f)) + -> decltype(detail::dispatcher<F, V, + typename detail::result_of_unary_visit<F, + typename detail::select_type<0, Types...>::type>::type, Types...>::apply(v, f)) { - return detail::dispatcher<F, V, Types...>::apply(v, f); + using R = typename detail::result_of_unary_visit<F, typename detail::select_type<0, Types...>::type>::type; + return detail::dispatcher<F, V, R, Types...>::apply(v, f); } // binary @@ -674,17 +699,23 @@ public: template <typename F, typename V> auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f)) + -> decltype(detail::binary_dispatcher<F, V, + typename detail::result_of_binary_visit<F, + typename detail::select_type<0, Types...>::type>::type, Types...>::apply_const(v0, v1, f)) { - return detail::binary_dispatcher<F, V, Types...>::apply_const(v0, v1, f); + using R = typename detail::result_of_binary_visit<F,typename detail::select_type<0, Types...>::type>::type; + return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, f); } // non-const template <typename F, typename V> auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f)) + -> decltype(detail::binary_dispatcher<F, V, + typename detail::result_of_binary_visit<F, + typename detail::select_type<0, Types...>::type>::type, Types...>::apply(v0, v1, f)) { - return detail::binary_dispatcher<F, V, Types...>::apply(v0, v1, f); + using R = typename detail::result_of_binary_visit<F,typename detail::select_type<0, Types...>::type>::type; + return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, f); } ~variant() noexcept @@ -745,28 +776,18 @@ auto VARIANT_INLINE static apply_visitor(F f, V & v0, V & v1) -> decltype(V::bin // getter interface template<typename ResultType, typename T> -ResultType & get(T & var) +ResultType & get(T & var) { return var.template get<ResultType>(); } template<typename ResultType, typename T> -ResultType const& get(T const& var) +ResultType const& get(T const& var) { return var.template get<ResultType>(); } -// 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; -} - }} #endif // MAPBOX_UTIL_VARIANT_HPP |