/usr/local/include/mapbox
Edit: /usr/local/include/mapbox/variant.hpp (31575B)
#ifndef MAPBOX_UTIL_VARIANT_HPP
#define MAPBOX_UTIL_VARIANT_HPP
#include
#include // size_t
#include // operator new
#include // runtime_error
#include
#include
#include
#include
#include
#include
#include
#include
// 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
template
struct MAPBOX_VARIANT_DEPRECATED 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;
};
#if __cpp_lib_logical_traits >= 201510L
using std::disjunction;
#else
template
struct disjunction : std::false_type {};
template
struct disjunction : B1 {};
template
struct disjunction : std::conditional::type {};
template
struct disjunction : std::conditional>::type {};
#endif
template
struct convertible_type;
template
struct convertible_type
{
static constexpr std::size_t index = std::is_convertible::value
? disjunction...>::value ? invalid_value : sizeof...(Types)
: convertible_type::index;
};
template
struct convertible_type
{
static constexpr std::size_t index = invalid_value;
};
template
struct value_traits
{
using value_type = typename std::remove_const::type>::type;
static constexpr std::size_t direct_index = direct_type::index;
static constexpr bool is_direct = direct_index != invalid_value;
static constexpr std::size_t index = is_direct ? direct_index : convertible_type::index;
static constexpr bool is_valid = index != invalid_value;
static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0;
using target_type = typename std::tuple_element>::type;
};
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;
};
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 type_index, void* data)
{
if (type_index == sizeof...(Types))
{
reinterpret_cast(data)->~T();
}
else
{
variant_helper::destroy(type_index, data);
}
}
VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value)
{
if (old_type_index == sizeof...(Types))
{
new (new_value) T(std::move(*reinterpret_cast(old_value)));
}
else
{
variant_helper::move(old_type_index, old_value, new_value);
}
}
VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value)
{
if (old_type_index == sizeof...(Types))
{
new (new_value) T(*reinterpret_cast(old_value));
}
else
{
variant_helper::copy(old_type_index, 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*) {}
};
template
struct unwrapper
{
static T const& apply_const(T const& obj) { return obj; }
static T& apply(T& obj) { return obj; }
};
template
struct unwrapper>
{
static auto apply_const(recursive_wrapper const& obj)
-> typename recursive_wrapper::type const&
{
return obj.get();
}
static auto apply(recursive_wrapper& obj)
-> typename recursive_wrapper::type&
{
return obj.get();
}
};
template
struct unwrapper>
{
static auto apply_const(std::reference_wrapper const& obj)
-> typename std::reference_wrapper::type const&
{
return obj.get();
}
static auto apply(std::reference_wrapper& obj)
-> typename std::reference_wrapper::type&
{
return obj.get();
}
};
template
struct dispatcher;
template
struct dispatcher
{
VARIANT_INLINE static R apply_const(V const& v, F&& f)
{
if (v.template is())
{
return f(unwrapper::apply_const(v.template get_unchecked()));
}
else
{
return dispatcher::apply_const(v, std::forward(f));
}
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
if (v.template is())
{
return f(unwrapper::apply(v.template get_unchecked()));
}
else
{
return dispatcher::apply(v, std::forward(f));
}
}
};
template
struct dispatcher
{
VARIANT_INLINE static R apply_const(V const& v, F&& f)
{
return f(unwrapper::apply_const(v.template get_unchecked()));
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
return f(unwrapper::apply(v.template get_unchecked()));
}
};
template
struct binary_dispatcher_rhs;
template
struct binary_dispatcher_rhs
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
if (rhs.template is()) // call binary functor
{
return f(unwrapper::apply_const(lhs.template get_unchecked()),
unwrapper::apply_const(rhs.template get_unchecked()));
}
else
{
return binary_dispatcher_rhs::apply_const(lhs, rhs, std::forward(f));
}
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (rhs.template is()) // call binary functor
{
return f(unwrapper::apply(lhs.template get_unchecked()),
unwrapper::apply(rhs.template get_unchecked()));
}
else
{
return binary_dispatcher_rhs::apply(lhs, rhs, std::forward(f));
}
}
};
template
struct binary_dispatcher_rhs
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
return f(unwrapper::apply_const(lhs.template get_unchecked()),
unwrapper::apply_const(rhs.template get_unchecked()));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper::apply(lhs.template get_unchecked()),
unwrapper::apply(rhs.template get_unchecked()));
}
};
template
struct binary_dispatcher_lhs;
template
struct binary_dispatcher_lhs
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
if (lhs.template is()) // call binary functor
{
return f(unwrapper::apply_const(lhs.template get_unchecked()),
unwrapper::apply_const(rhs.template get_unchecked()));
}
else
{
return binary_dispatcher_lhs::apply_const(lhs, rhs, std::forward(f));
}
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (lhs.template is()) // call binary functor
{
return f(unwrapper::apply(lhs.template get_unchecked()),
unwrapper::apply(rhs.template get_unchecked()));
}
else
{
return binary_dispatcher_lhs::apply(lhs, rhs, std::forward(f));
}
}
};
template
struct binary_dispatcher_lhs
{
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
{
return f(unwrapper::apply_const(lhs.template get_unchecked()),
unwrapper::apply_const(rhs.template get_unchecked()));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper::apply(lhs.template get_unchecked()),
unwrapper::apply(rhs.template get_unchecked()));
}
};
template
struct binary_dispatcher;
template
struct binary_dispatcher
{
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
{
if (v0.template is())
{
if (v1.template is())
{
return f(unwrapper::apply_const(v0.template get_unchecked()),
unwrapper::apply_const(v1.template get_unchecked())); // call binary functor
}
else
{
return binary_dispatcher_rhs::apply_const(v0, v1, std::forward(f));
}
}
else if (v1.template is())
{
return binary_dispatcher_lhs::apply_const(v0, v1, std::forward(f));
}
return binary_dispatcher::apply_const(v0, v1, std::forward(f));
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
if (v0.template is())
{
if (v1.template is())
{
return f(unwrapper::apply(v0.template get_unchecked()),
unwrapper::apply(v1.template get_unchecked())); // call binary functor
}
else
{
return binary_dispatcher_rhs::apply(v0, v1, std::forward(f));
}
}
else if (v1.template is())
{
return binary_dispatcher_lhs::apply(v0, v1, std::forward(f));
}
return binary_dispatcher::apply(v0, v1, std::forward(f));
}
};
template
struct binary_dispatcher
{
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
{
return f(unwrapper::apply_const(v0.template get_unchecked()),
unwrapper::apply_const(v1.template get_unchecked())); // call binary functor
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
return f(unwrapper::apply(v0.template get_unchecked()),
unwrapper::apply(v1.template get_unchecked())); // call binary functor
}
};
// 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_unchecked();
return Comp()(lhs_content, rhs_content);
}
private:
Variant const& lhs_;
};
// hashing visitor
struct hasher
{
template
std::size_t operator()(const T& hashable) const
{
return std::hash{}(hashable);
}
};
} // namespace detail
struct no_init
{
};
template
class variant
{
static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty");
static_assert(!detail::disjunction...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
private:
static const std::size_t data_size = detail::static_max::value;
static const std::size_t data_align = detail::static_max::value;
public:
struct adapted_variant_tag;
using types = std::tuple;
private:
using first_type = typename std::tuple_element<0, types>::type;
using data_type = typename std::aligned_storage::type;
using helper_type = detail::variant_helper;
std::size_t type_index;
data_type data;
public:
VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible::value)
: type_index(sizeof...(Types)-1)
{
static_assert(std::is_default_constructible::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 Enable = typename std::enable_if, typename Traits::value_type>::value>::type >
VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible::value)
: type_index(Traits::index)
{
new (&data) typename Traits::target_type(std::forward(val));
}
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(std::is_nothrow_move_constructible::value)
: type_index(old.type_index)
{
helper_type::move(old.type_index, &old.data, &data);
}
private:
VARIANT_INLINE void copy_assign(variant 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&& 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& operator=(variant&& other)
{
move_assign(std::move(other));
return *this;
}
VARIANT_INLINE variant& operator=(variant const& other)
{
copy_assign(other);
return *this;
}
// conversions
// move-assign
template
VARIANT_INLINE variant& operator=(T&& rhs) noexcept
{
variant temp(std::forward(rhs));
move_assign(std::move(temp));
return *this;
}
// copy-assign
template
VARIANT_INLINE variant& operator=(T const& rhs)
{
variant temp(rhs);
copy_assign(temp);
return *this;
}
template ::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE bool is() const
{
return type_index == detail::direct_type::index;
}
template , Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE bool is() const
{
return type_index == detail::direct_type, Types...>::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);
type_index = detail::invalid_value;
new (&data) T(std::forward(args)...);
type_index = detail::direct_type::index;
}
// get_unchecked()
template ::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get_unchecked()
{
return *reinterpret_cast(&data);
}
#ifdef HAS_EXCEPTIONS
// 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 bad_variant_access("in get()");
}
}
#endif
template ::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T const& get_unchecked() const
{
return *reinterpret_cast(&data);
}
#ifdef HAS_EXCEPTIONS
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 bad_variant_access("in get()");
}
}
#endif
// get_unchecked() - T stored as recursive_wrapper
template , Types...>::index != detail::invalid_value)>::type* = nullptr>
VARIANT_INLINE T& get_unchecked()
{
return (*reinterpret_cast*>(&data)).get();
}
#ifdef HAS_EXCEPTIONS
// get