update mapbox::variant

This commit is contained in:
Konstantin Käfer
2015-02-11 11:18:54 -08:00
parent fb44fc81bd
commit 86455585ee
3 changed files with 146 additions and 83 deletions

View File

@@ -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

View File

@@ -0,0 +1,41 @@
#ifndef MAPBOX_UTIL_VARIANT_IO_HPP
#define MAPBOX_UTIL_VARIANT_IO_HPP
#include "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;
}
}}
#endif //MAPBOX_UTIL_VARIANT_IO_HPP

View File

@@ -1,5 +1,6 @@
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/style/filter_expression_private.hpp>
#include <mbgl/util/variant_io.hpp>
#include <algorithm>
#include <iostream>