rename and remove include header files for stabilized lib API

This commit is contained in:
Dennis Luxen
2014-11-24 17:55:45 +01:00
parent 1d2f06df6d
commit 59e9a67abd
10 changed files with 0 additions and 0 deletions
-74
View File
@@ -1,74 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.
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.
*/
#ifndef REPLY_H
#define REPLY_H
#include "Header.h"
#include <boost/asio.hpp>
#include <vector>
namespace http
{
const char okHTML[] = "";
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
const char internalServerErrorHTML[] =
"{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
const char seperators[] = {':', ' '};
const char crlf[] = {'\r', '\n'};
const std::string okString = "HTTP/1.0 200 OK\r\n";
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
class Reply
{
public:
enum status_type
{ ok = 200,
badRequest = 400,
internalServerError = 500 } status;
std::vector<Header> headers;
std::vector<boost::asio::const_buffer> ToBuffers();
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::vector<char> content;
static Reply StockReply(status_type status);
void SetSize(const unsigned size);
void SetUncompressedSize();
Reply();
private:
std::string ToString(Reply::status_type status);
boost::asio::const_buffer ToBuffer(Reply::status_type status);
};
}
#endif // REPLY_H
@@ -25,29 +25,70 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HTTP_HEADER_H
#define HTTP_HEADER_H
// based on
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
#ifndef JSON_CONTAINER_H
#define JSON_CONTAINER_H
#include <variant/variant.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <unordered_map>
namespace http
namespace JSON
{
struct Header
struct Object;
struct Array;
struct String
{
Header& operator=(const Header& other) = default;
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
void Clear()
{
name.clear();
value.clear();
}
std::string name;
String() {}
String(const char *value) : value(value) {}
String(const std::string &value) : value(value) {}
std::string value;
};
}
#endif // HTTP_HEADER_H
struct Number
{
Number() {}
Number(double value) : value(static_cast<double>(value)) {}
double value;
};
struct True
{
};
struct False
{
};
struct Null
{
};
using Value = mapbox::util::variant<String,
Number,
mapbox::util::recursive_wrapper<Object>,
mapbox::util::recursive_wrapper<Array>,
True,
False,
Null>;
struct Object
{
std::unordered_map<std::string, Value> values;
};
struct Array
{
std::vector<Value> values;
};
} // namespace JSON
#endif // JSON_CONTAINER_H
+69
View File
@@ -0,0 +1,69 @@
#ifndef MAPBOX_UTIL_OPTIONAL_HPP
#define MAPBOX_UTIL_OPTIONAL_HPP
#include <type_traits>
#include "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{}; }
};
}
}
#endif
+127
View File
@@ -0,0 +1,127 @@
#ifndef MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#define MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
#include <utility>
namespace mapbox { namespace util {
template <typename T>
class recursive_wrapper
{
public:
using type = T;
private:
T* p_;
public:
~recursive_wrapper();
recursive_wrapper();
recursive_wrapper(recursive_wrapper const& operand);
recursive_wrapper(T const& operand);
recursive_wrapper(recursive_wrapper&& operand);
recursive_wrapper(T&& operand);
private:
void assign(const T& rhs);
public:
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;
}
public:
T& get() { return *get_pointer(); }
const T& get() const { 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(); }
};
template <typename T>
recursive_wrapper<T>::~recursive_wrapper()
{
delete p_;
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper()
: p_(new T)
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(recursive_wrapper const& operand)
: p_(new T( operand.get() ))
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(T const& operand)
: p_(new T(operand))
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(recursive_wrapper&& operand)
: p_(operand.p_)
{
operand.p_ = nullptr;
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(T&& operand)
: p_(new T( std::move(operand) ))
{
}
template <typename T>
void recursive_wrapper<T>::assign(const T& rhs)
{
this->get() = rhs;
}
template <typename T>
inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
{
lhs.swap(rhs);
}
}}
#endif // MAPBOX_UTIL_VARIANT_RECURSIVE_WRAPPER_HPP
+740
View File
@@ -0,0 +1,740 @@
#ifndef MAPBOX_UTIL_VARIANT_HPP
#define MAPBOX_UTIL_VARIANT_HPP
#include <utility>
#include <typeinfo>
#include <type_traits>
#include <stdexcept> // runtime_error
#include <new> // operator new
#include <cstddef> // size_t
#include <iosfwd>
#include <string>
#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 { namespace detail {
static constexpr std::size_t invalid_value = std::size_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 std::size_t index = std::is_same<T, First>::value
? sizeof...(Types) : direct_type<T, Types...>::index;
};
template <typename T>
struct direct_type<T>
{
static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
struct convertible_type;
template <typename T, typename First, typename...Types>
struct convertible_type<T, First, Types...>
{
static constexpr std::size_t index = std::is_convertible<T, First>::value
? sizeof...(Types) : convertible_type<T, Types...>::index;
};
template <typename T>
struct convertible_type<T>
{
static constexpr std::size_t index = invalid_value;
};
template <typename T, typename...Types>
struct value_traits
{
static constexpr std::size_t direct_index = direct_type<T, Types...>::index;
static constexpr std::size_t index =
(direct_index == invalid_value) ? convertible_type<T, Types...>::index : direct_index;
};
template <typename T, typename...Types>
struct is_valid_type;
template <typename T, typename First, typename... Types>
struct is_valid_type<T, First, Types...>
{
static constexpr bool value = std::is_convertible<T, First>::value
|| is_valid_type<T, Types...>::value;
};
template <typename T>
struct is_valid_type<T> : std::false_type {};
template <std::size_t N, typename ... Types>
struct select_type
{
static_assert(N < sizeof...(Types), "index out of bounds");
};
template <std::size_t N, typename T, typename ... Types>
struct select_type<N, T, Types...>
{
using type = typename select_type<N - 1, Types...>::type;
};
template <typename T, typename ... Types>
struct select_type<0, T, Types...>
{
using type = T;
};
} // namespace detail
// static visitor
template <typename R = void>
struct static_visitor
{
using result_type = R;
protected:
static_visitor() {}
~static_visitor() {}
};
template <std::size_t arg1, std::size_t ... others>
struct static_max;
template <std::size_t arg>
struct static_max<arg>
{
static const std::size_t value = arg;
};
template <std::size_t arg1, std::size_t arg2, std::size_t ... others>
struct static_max<arg1, arg2, others...>
{
static const std::size_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 std::size_t id, void * data)
{
if (id == sizeof...(Types))
{
reinterpret_cast<T*>(data)->~T();
}
else
{
variant_helper<Types...>::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<T*>(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<Types...>::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<const T*>(old_value));
}
else
{
variant_helper<Types...>::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 <typename T>
struct unwrapper
{
T const& operator() (T const& obj) const
{
return obj;
}
T& operator() (T & obj) const
{
return obj;
}
};
template <typename T>
struct unwrapper<recursive_wrapper<T>>
{
auto operator() (recursive_wrapper<T> const& obj) const
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
}
};
template <typename F, typename V, typename...Types>
struct dispatcher;
template <typename F, typename V, typename T, typename...Types>
struct dispatcher<F, V, T, Types...>
{
using result_type = typename F::result_type;
VARIANT_INLINE static result_type apply_const(V const& v, F f)
{
if (v.get_type_index() == sizeof...(Types))
{
return f(unwrapper<T>()(v. template get<T>()));
}
else
{
return dispatcher<F, V, Types...>::apply_const(v, f);
}
}
VARIANT_INLINE static result_type apply(V & v, F f)
{
if (v.get_type_index() == sizeof...(Types))
{
return f(unwrapper<T>()(v. template get<T>()));
}
else
{
return dispatcher<F, V, Types...>::apply(v, f);
}
}
};
template<typename F, typename V>
struct dispatcher<F, V>
{
using result_type = typename F::result_type;
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 <typename F, typename V, 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...>
{
using result_type = typename F::result_type;
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<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, T0, Types...>::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<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, T0, Types...>::apply(lhs, rhs, f);
}
}
};
template<typename F, typename V, typename T>
struct binary_dispatcher_rhs<F, V, T>
{
using result_type = typename F::result_type;
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 <typename F, typename V, 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...>
{
using result_type = typename F::result_type;
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<T1>(), rhs. template get<T0>());
}
else
{
return binary_dispatcher_lhs<F, V, T0, Types...>::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<T1>(), rhs. template get<T0>());
}
else
{
return binary_dispatcher_lhs<F, V, T0, Types...>::apply(lhs, rhs, f);
}
}
};
template<typename F, typename V, typename T>
struct binary_dispatcher_lhs<F, V, T>
{
using result_type = typename F::result_type;
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 <typename F, typename V, typename...Types>
struct binary_dispatcher;
template <typename F, typename V, typename T, typename...Types>
struct binary_dispatcher<F, V, T, Types...>
{
using result_type = typename F::result_type;
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<T>(), v1. template get<T>()); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, 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<F, V, Types...>::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<T>(), v1. template get<T>()); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, 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<F, V, Types...>::apply(v0, v1, f);
}
};
template<typename F, typename V>
struct binary_dispatcher<F, V>
{
using result_type = typename F::result_type;
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 <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 static_visitor<bool>
{
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<T>();
return Comp()(lhs_content, rhs_content);
}
private:
Variant const& lhs_;
};
// operator<< helper
template <typename Out>
class printer : public static_visitor<>
{
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
struct no_init {};
template<typename... Types>
class variant
{
private:
static const std::size_t data_size = static_max<sizeof(Types)...>::value;
static const std::size_t data_align = static_max<alignof(Types)...>::value;
using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = variant_helper<Types...>;
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 <typename T, class = typename std::enable_if<
detail::is_valid_type<typename std::remove_reference<T>::type, Types...>::value>::type>
VARIANT_INLINE variant(T && val) noexcept
: type_index(detail::value_traits<typename std::remove_reference<T>::type, Types...>::index)
{
constexpr std::size_t index = sizeof...(Types) - detail::value_traits<typename std::remove_reference<T>::type, Types...>::index - 1;
using target_type = typename detail::select_type<index, Types...>::type;
new (&data) target_type(std::forward<T>(val)); // nothrow
}
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
: type_index(old.type_index)
{
helper_type::move(old.type_index, &old.data, &data);
}
friend void swap(variant<Types...> & first, variant<Types...> & second)
{
using std::swap; //enable ADL
swap(first.type_index, second.type_index);
swap(first.data, second.data);
}
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> other)
{
swap(*this, other);
return *this;
}
// conversions
// move-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T && rhs) noexcept
{
variant<Types...> temp(std::forward<T>(rhs));
swap(*this, temp);
return *this;
}
// copy-assign
template <typename T>
VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
{
variant<Types...> temp(rhs);
swap(*this, temp);
return *this;
}
template<typename T>
VARIANT_INLINE bool is() const
{
return (type_index == detail::direct_type<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);
new (&data) T(std::forward<Args>(args)...);
type_index = detail::direct_type<T, Types...>::index;
}
template<typename T>
VARIANT_INLINE T& get()
{
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T*>(&data);
}
else
{
throw std::runtime_error("in get()");
}
}
template<typename T>
VARIANT_INLINE T const& get() const
{
if (type_index == detail::direct_type<T, Types...>::index)
{
return *reinterpret_cast<T const*>(&data);
}
else
{
throw std::runtime_error("in get()");
}
}
VARIANT_INLINE std::size_t get_type_index() const
{
return type_index;
}
// 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))
{
return detail::dispatcher<F, V, 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))
{
return detail::dispatcher<F, V, Types...>::apply(v, f);
}
// binary
// const
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))
{
return detail::binary_dispatcher<F, V, 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))
{
return detail::binary_dispatcher<F, V, Types...>::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<variant, detail::equal_comp> 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<variant, detail::less_comp> visitor(*this);
return visit(rhs, visitor);
}
};
// unary visitor interface
// const
template <typename V, typename F>
auto VARIANT_INLINE static apply_visitor(F f, V const& v) -> decltype(V::visit(v, f))
{
return V::visit(v, f);
}
// non-const
template <typename V, typename F>
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 <typename V, typename F>
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 <typename V, typename F>
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<typename ResultType, typename T>
ResultType & get(T & var)
{
return var.template get<ResultType>();
}
template<typename ResultType, typename T>
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