diff -Nru mapbox-variant-1.1.0/debian/changelog mapbox-variant-1.1.5/debian/changelog --- mapbox-variant-1.1.0/debian/changelog 2016-06-26 11:40:56.000000000 +0000 +++ mapbox-variant-1.1.5/debian/changelog 2017-06-02 18:33:11.000000000 +0000 @@ -1,8 +1,50 @@ -mapbox-variant (1.1.0-2~xenial0) xenial; urgency=medium +mapbox-variant (1.1.5-1~xenial0) xenial; urgency=medium * No change rebuild for Xenial. - -- Angelos Tzotsos Sun, 26 Jun 2016 14:00:00 +0200 + -- Angelos Tzotsos Fri, 02 Jun 2017 19:00:00 +0200 + +mapbox-variant (1.1.5-1) unstable; urgency=medium + + * New upstream release. + * Refresh patches. + + -- Bas Couwenberg Wed, 18 Jan 2017 21:48:11 +0100 + +mapbox-variant (1.1.4-1) unstable; urgency=medium + + * New upstream release. + * Refresh patches. + + -- Bas Couwenberg Wed, 23 Nov 2016 20:16:44 +0100 + +mapbox-variant (1.1.3-1) unstable; urgency=medium + + * New upstream release. + + -- Bas Couwenberg Mon, 24 Oct 2016 19:59:18 +0200 + +mapbox-variant (1.1.2-1) unstable; urgency=medium + + * Move from experimental to unstable. + + -- Bas Couwenberg Thu, 08 Sep 2016 15:18:46 +0200 + +mapbox-variant (1.1.2-1~exp1) experimental; urgency=medium + + * New upstream release. + + -- Bas Couwenberg Tue, 26 Jul 2016 13:31:22 +0200 + +mapbox-variant (1.1.1-1~exp1) experimental; urgency=medium + + * New upstream release. + * Bump Standards-Version to 3.9.8, no changes. + * Update copyright file, update path for recursive_wrapper.hpp. + * Update paths in install file. + * Add patch to disable mason, not required for Debian package build. + + -- Bas Couwenberg Tue, 19 Jul 2016 01:37:49 +0200 mapbox-variant (1.1.0-2) unstable; urgency=medium diff -Nru mapbox-variant-1.1.0/debian/control mapbox-variant-1.1.5/debian/control --- mapbox-variant-1.1.0/debian/control 2016-02-26 21:25:40.000000000 +0000 +++ mapbox-variant-1.1.5/debian/control 2016-04-17 16:48:01.000000000 +0000 @@ -8,7 +8,7 @@ libboost-system-dev, libboost-timer-dev, libboost-chrono-dev -Standards-Version: 3.9.7 +Standards-Version: 3.9.8 Vcs-Browser: https://anonscm.debian.org/cgit/pkg-grass/mapbox-variant.git/ Vcs-Git: https://anonscm.debian.org/git/pkg-grass/mapbox-variant.git Homepage: https://github.com/mapbox/variant diff -Nru mapbox-variant-1.1.0/debian/copyright mapbox-variant-1.1.5/debian/copyright --- mapbox-variant-1.1.0/debian/copyright 2016-02-28 23:26:01.000000000 +0000 +++ mapbox-variant-1.1.5/debian/copyright 2016-07-18 16:23:34.000000000 +0000 @@ -7,7 +7,7 @@ Copyright: MapBox License: BSD-3-Clause -Files: recursive_wrapper.hpp +Files: include/mapbox/recursive_wrapper.hpp Copyright: 2002-2003, Eric Friedman 2002-2003, Itay Maman License: BSL-1.0 diff -Nru mapbox-variant-1.1.0/debian/install mapbox-variant-1.1.5/debian/install --- mapbox-variant-1.1.0/debian/install 2016-02-26 21:01:46.000000000 +0000 +++ mapbox-variant-1.1.5/debian/install 2016-07-18 22:59:27.000000000 +0000 @@ -1 +1 @@ -*.hpp /usr/include/mapbox/variant +include/ usr/ diff -Nru mapbox-variant-1.1.0/debian/patches/disble-mason.patch mapbox-variant-1.1.5/debian/patches/disble-mason.patch --- mapbox-variant-1.1.0/debian/patches/disble-mason.patch 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/debian/patches/disble-mason.patch 2017-01-18 20:07:20.000000000 +0000 @@ -0,0 +1,28 @@ +Description: Disbale mason, not required for Debian package build. +Author: Bas Couwenberg +Forwarded: not-needed + +--- a/Makefile ++++ b/Makefile +@@ -5,7 +5,7 @@ CXX := $(CXX) + CXX_STD ?= c++11 + + BOOST_ROOT = $(shell $(MASON) prefix boost $(BOOST_VERSION)) +-BOOST_FLAGS = -isystem $(BOOST_ROOT)/include/ ++BOOST_FLAGS = + RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -fvisibility=hidden + DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -fno-omit-frame-pointer -fPIE + WARNING_FLAGS = -Werror -Wall -Wextra -pedantic \ +@@ -44,10 +44,10 @@ ALL_HEADERS = $(shell find include/mapbo + all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test + + $(MASON): +- git submodule update --init .mason ++# git submodule update --init .mason + + mason_packages/headers/boost: $(MASON) +- $(MASON) install boost $(BOOST_VERSION) ++# $(MASON) install boost $(BOOST_VERSION) + + ./deps/gyp: + git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp diff -Nru mapbox-variant-1.1.0/debian/patches/series mapbox-variant-1.1.5/debian/patches/series --- mapbox-variant-1.1.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/debian/patches/series 2016-07-18 22:59:27.000000000 +0000 @@ -0,0 +1 @@ +disble-mason.patch diff -Nru mapbox-variant-1.1.0/.gitignore mapbox-variant-1.1.5/.gitignore --- mapbox-variant-1.1.0/.gitignore 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/.gitignore 2017-01-08 19:20:43.000000000 +0000 @@ -6,3 +6,4 @@ *.gcda *.gcno .ycm_extra_conf.pyc +mason_packages diff -Nru mapbox-variant-1.1.0/.gitmodules mapbox-variant-1.1.5/.gitmodules --- mapbox-variant-1.1.0/.gitmodules 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/.gitmodules 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,3 @@ +[submodule ".mason"] + path = .mason + url = https://github.com/mapbox/mason.git diff -Nru mapbox-variant-1.1.0/include/mapbox/optional.hpp mapbox-variant-1.1.5/include/mapbox/optional.hpp --- mapbox-variant-1.1.0/include/mapbox/optional.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/include/mapbox/optional.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,74 @@ +#ifndef MAPBOX_UTIL_OPTIONAL_HPP +#define MAPBOX_UTIL_OPTIONAL_HPP + +#pragma message("This implementation of optional is deprecated. See https://github.com/mapbox/variant/issues/64.") + +#include +#include + +#include + +namespace mapbox { +namespace util { + +template +class optional +{ + static_assert(!std::is_reference::value, "optional doesn't support references"); + + struct none_type + { + }; + + variant 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 const& get() const { return variant_.template get(); } + T& get() { return variant_.template get(); } + + 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 + void emplace(Args&&... args) + { + variant_ = T{std::forward(args)...}; + } + + void reset() { variant_ = none_type{}; } + +}; // class optional + +} // namespace util +} // namespace mapbox + +#endif // MAPBOX_UTIL_OPTIONAL_HPP diff -Nru mapbox-variant-1.1.0/include/mapbox/recursive_wrapper.hpp mapbox-variant-1.1.5/include/mapbox/recursive_wrapper.hpp --- mapbox-variant-1.1.0/include/mapbox/recursive_wrapper.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/include/mapbox/recursive_wrapper.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,122 @@ +#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP +#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP + +// Based on variant/recursive_wrapper.hpp from boost. +// +// Original license: +// +// Copyright (c) 2002-2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace mapbox { +namespace util { + +template +class recursive_wrapper +{ + + T* p_; + + void assign(T const& rhs) + { + this->get() = rhs; + } + +public: + using type = T; + + /** + * Default constructor default initializes the internally stored value. + * For POD types this means nothing is done and the storage is + * uninitialized. + * + * @throws std::bad_alloc if there is insufficient memory for an object + * of type T. + * @throws any exception thrown by the default constructur of T. + */ + recursive_wrapper() + : p_(new T){} + + ~recursive_wrapper() noexcept { delete p_; } + + recursive_wrapper(recursive_wrapper const& operand) + : p_(new T(operand.get())) {} + + recursive_wrapper(T const& operand) + : p_(new T(operand)) {} + + recursive_wrapper(recursive_wrapper&& operand) + : p_(new T(std::move(operand.get()))) {} + + recursive_wrapper(T&& operand) + : p_(new T(std::move(operand))) {} + + 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; + } + + T& get() + { + assert(p_); + return *get_pointer(); + } + + T const& get() const + { + assert(p_); + 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(); } + +}; // class recursive_wrapper + +template +inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept +{ + lhs.swap(rhs); +} +} // namespace util +} // namespace mapbox + +#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP diff -Nru mapbox-variant-1.1.0/include/mapbox/variant.hpp mapbox-variant-1.1.5/include/mapbox/variant.hpp --- mapbox-variant-1.1.0/include/mapbox/variant.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/include/mapbox/variant.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,1027 @@ +#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::conjunction; +using std::disjunction; + +#else + +template +struct conjunction : std::true_type {}; + +template +struct conjunction : B1 {}; + +template +struct conjunction : std::conditional::type {}; + +template +struct conjunction : std::conditional, B1>::type {}; + +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(detail::conjunction...>::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() - 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 bad_variant_access("in get()"); + } + } +#endif + + template , Types...>::index != detail::invalid_value)>::type* = nullptr> + VARIANT_INLINE T const& get_unchecked() const + { + return (*reinterpret_cast const*>(&data)).get(); + } + +#ifdef HAS_EXCEPTIONS + 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 bad_variant_access("in get()"); + } + } +#endif + + // get_unchecked() - T stored as std::reference_wrapper + template , Types...>::index != detail::invalid_value)>::type* = nullptr> + VARIANT_INLINE T& get_unchecked() + { + return (*reinterpret_cast*>(&data)).get(); + } + +#ifdef HAS_EXCEPTIONS + // get() - T stored as std::reference_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 bad_variant_access("in get()"); + } + } +#endif + + template , Types...>::index != detail::invalid_value)>::type* = nullptr> + VARIANT_INLINE T const& get_unchecked() const + { + return (*reinterpret_cast const*>(&data)).get(); + } + +#ifdef HAS_EXCEPTIONS + 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 bad_variant_access("in get()"); + } + } +#endif + + // This function is deprecated because it returns an internal index field. + // Use which() instead. + MAPBOX_VARIANT_DEPRECATED 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); + } + + template ::index != detail::invalid_value)>::type* = nullptr> + VARIANT_INLINE static constexpr int which() noexcept + { + return static_cast(sizeof...(Types)-detail::direct_type::index - 1); + } + + // visitor + // unary + template ::type> + auto VARIANT_INLINE static visit(V const& v, F&& f) + -> decltype(detail::dispatcher::apply_const(v, std::forward(f))) + { + return detail::dispatcher::apply_const(v, std::forward(f)); + } + // non-const + template ::type> + auto VARIANT_INLINE static visit(V& v, F&& f) + -> decltype(detail::dispatcher::apply(v, std::forward(f))) + { + return detail::dispatcher::apply(v, std::forward(f)); + } + + // binary + // const + template ::type> + auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f) + -> decltype(detail::binary_dispatcher::apply_const(v0, v1, std::forward(f))) + { + return detail::binary_dispatcher::apply_const(v0, v1, std::forward(f)); + } + // non-const + template ::type> + auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f) + -> decltype(detail::binary_dispatcher::apply(v0, v1, std::forward(f))) + { + return detail::binary_dispatcher::apply(v0, v1, std::forward(f)); + } + + // match + // unary + template + auto VARIANT_INLINE match(Fs&&... fs) const + -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...))) + { + return variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...)); + } + // non-const + template + auto VARIANT_INLINE match(Fs&&... fs) + -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...))) + { + return variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...)); + } + + ~variant() noexcept // no-throw destructor + { + helper_type::destroy(type_index, &data); + } + + // comparison operators + // equality + VARIANT_INLINE bool operator==(variant const& rhs) const + { + assert(valid() && rhs.valid()); + if (this->which() != rhs.which()) + { + return false; + } + detail::comparer visitor(*this); + return visit(rhs, visitor); + } + + VARIANT_INLINE bool operator!=(variant const& rhs) const + { + return !(*this == rhs); + } + + // less than + VARIANT_INLINE bool operator<(variant const& rhs) const + { + assert(valid() && rhs.valid()); + if (this->which() != rhs.which()) + { + return this->which() < rhs.which(); + } + detail::comparer visitor(*this); + return visit(rhs, visitor); + } + VARIANT_INLINE bool operator>(variant const& rhs) const + { + return rhs < *this; + } + VARIANT_INLINE bool operator<=(variant const& rhs) const + { + return !(*this > rhs); + } + VARIANT_INLINE bool operator>=(variant const& rhs) const + { + return !(*this < rhs); + } +}; + +// unary visitor interface +// const +template +auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward(f))) +{ + return V::visit(v, std::forward(f)); +} + +// non-const +template +auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward(f))) +{ + return V::visit(v, std::forward(f)); +} + +// binary visitor interface +// const +template +auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) +{ + return V::binary_visit(v0, v1, std::forward(f)); +} + +// non-const +template +auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) +{ + return V::binary_visit(v0, v1, std::forward(f)); +} + +// getter interface + +#ifdef HAS_EXCEPTIONS +template +auto get(T& var)->decltype(var.template get()) +{ + return var.template get(); +} +#endif + +template +ResultType& get_unchecked(T& var) +{ + return var.template get_unchecked(); +} + +#ifdef HAS_EXCEPTIONS +template +auto get(T const& var)->decltype(var.template get()) +{ + return var.template get(); +} +#endif + +template +ResultType const& get_unchecked(T const& var) +{ + return var.template get_unchecked(); +} +} // namespace util +} // namespace mapbox + +// hashable iff underlying types are hashable +namespace std { +template +struct hash< ::mapbox::util::variant> { + std::size_t operator()(const ::mapbox::util::variant& v) const noexcept + { + return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v); + } +}; +} + +#endif // MAPBOX_UTIL_VARIANT_HPP diff -Nru mapbox-variant-1.1.0/include/mapbox/variant_io.hpp mapbox-variant-1.1.5/include/mapbox/variant_io.hpp --- mapbox-variant-1.1.0/include/mapbox/variant_io.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/include/mapbox/variant_io.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,45 @@ +#ifndef MAPBOX_UTIL_VARIANT_IO_HPP +#define MAPBOX_UTIL_VARIANT_IO_HPP + +#include + +#include + +namespace mapbox { +namespace util { + +namespace detail { +// operator<< helper +template +class printer +{ +public: + explicit printer(Out& out) + : out_(out) {} + printer& operator=(printer const&) = delete; + + // visitor + template + void operator()(T const& operand) const + { + out_ << operand; + } + +private: + Out& out_; +}; +} + +// operator<< +template +VARIANT_INLINE std::basic_ostream& +operator<<(std::basic_ostream& out, variant const& rhs) +{ + detail::printer> visitor(out); + apply_visitor(visitor, rhs); + return out; +} +} // namespace util +} // namespace mapbox + +#endif // MAPBOX_UTIL_VARIANT_IO_HPP diff -Nru mapbox-variant-1.1.0/include/mapbox/variant_visitor.hpp mapbox-variant-1.1.5/include/mapbox/variant_visitor.hpp --- mapbox-variant-1.1.0/include/mapbox/variant_visitor.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/include/mapbox/variant_visitor.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,38 @@ +#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP +#define MAPBOX_UTIL_VARIANT_VISITOR_HPP + +namespace mapbox { +namespace util { + +template +struct visitor; + +template +struct visitor : Fn +{ + using type = Fn; + using Fn::operator(); + + visitor(Fn fn) : Fn(fn) {} +}; + +template +struct visitor : Fn, visitor +{ + using type = visitor; + using Fn::operator(); + using visitor::operator(); + + visitor(Fn fn, Fns... fns) : Fn(fn), visitor(fns...) {} +}; + +template +visitor make_visitor(Fns... fns) +{ + return visitor(fns...); +} + +} // namespace util +} // namespace mapbox + +#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP diff -Nru mapbox-variant-1.1.0/Jamroot mapbox-variant-1.1.5/Jamroot --- mapbox-variant-1.1.0/Jamroot 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/Jamroot 2017-01-08 19:20:43.000000000 +0000 @@ -1,4 +1,4 @@ -# Inofficial and incomplete build file using Boost build system. +# Unofficial and incomplete build file using Boost build system. # You should use make unless you know what you are doing. local BOOST_DIR = "/usr/local" ; @@ -17,9 +17,10 @@ .//chrono : $(BOOST_DIR)/include - ./ + ./include + ./test/include #SINGLE_THREADED - release:-march=native + release:"-march=native -Wweak-vtables" ; @@ -31,7 +32,8 @@ .//chrono : $(BOOST_DIR)/include - ./ + ./include + ./test/include release:-march=native ; @@ -43,7 +45,8 @@ .//chrono : $(BOOST_DIR)/include - ./ + ./include + ./test/include release:-march=native ; @@ -55,7 +58,8 @@ .//chrono : $(BOOST_DIR)/include - ./ + ./include + ./test/include release:-march=native ; @@ -68,6 +72,7 @@ .//chrono : $(BOOST_DIR)/include - ./ + ./include + ./test/include release:-march=native ; diff -Nru mapbox-variant-1.1.0/Makefile mapbox-variant-1.1.5/Makefile --- mapbox-variant-1.1.0/Makefile 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/Makefile 2017-01-08 19:20:43.000000000 +0000 @@ -1,32 +1,53 @@ +MASON = .mason/mason +BOOST_VERSION = 1.62.0 CXX := $(CXX) CXX_STD ?= c++11 -BOOST_LIBS = -lboost_timer -lboost_system -lboost_chrono -RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -COMMON_FLAGS = -Wall -pedantic -Wextra -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -std=$(CXX_STD) +BOOST_ROOT = $(shell $(MASON) prefix boost $(BOOST_VERSION)) +BOOST_FLAGS = -isystem $(BOOST_ROOT)/include/ +RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -fvisibility=hidden +DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -fno-omit-frame-pointer -fPIE +WARNING_FLAGS = -Werror -Wall -Wextra -pedantic \ + -Wformat=2 -Wsign-conversion -Wshadow -Wunused-parameter + +COMMON_FLAGS = -std=$(CXX_STD) +COMMON_FLAGS += $(WARNING_FLAGS) + CXXFLAGS := $(CXXFLAGS) LDFLAGS := $(LDFLAGS) -OS:=$(shell uname -s) -ifeq ($(OS),Darwin) - CXXFLAGS += -stdlib=libc++ - LDFLAGS += -stdlib=libc++ -F/ -framework CoreFoundation -else - BOOST_LIBS += -lrt +export BUILDTYPE ?= Release + +OS := $(shell uname -s) +ifeq ($(OS), Linux) + EXTRA_FLAGS = -pthread endif +ifeq ($(OS), Darwin) + OSX_OLDEST_SUPPORTED ?= 10.7 + # we need to explicitly ask for libc++ otherwise the + # default will flip back to libstdc++ for mmacosx-version-min < 10.9 + EXTRA_FLAGS = -stdlib=libc++ -mmacosx-version-min=$(OSX_OLDEST_SUPPORTED) +endif + -ifeq (sizes,$(firstword $(MAKECMDGOALS))) - RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) - $(eval $(RUN_ARGS):;@:) - ifndef RUN_ARGS - $(error sizes target requires you pass full path to boost variant.hpp) - endif - .PHONY: $(RUN_ARGS) +ifeq ($(BUILDTYPE),Release) + FINAL_CXXFLAGS := $(COMMON_FLAGS) $(RELEASE_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS) +else + FINAL_CXXFLAGS := $(COMMON_FLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS) endif -all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test + + +ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')') + +all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test + +$(MASON): + git submodule update --init .mason + +mason_packages/headers/boost: $(MASON) + $(MASON) install boost $(BOOST_VERSION) ./deps/gyp: git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp @@ -34,27 +55,35 @@ gyp: ./deps/gyp deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make make V=1 -C ./out tests - ./out/Release/tests + ./out/$(BUILDTYPE)/tests + +out/bench-variant-debug: Makefile mason_packages/headers/boost test/bench_variant.cpp + mkdir -p ./out + $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) + +out/bench-variant: Makefile mason_packages/headers/boost test/bench_variant.cpp + mkdir -p ./out + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -out/bench-variant-debug: Makefile test/bench_variant.cpp variant.hpp recursive_wrapper.hpp +out/unique_ptr_test: Makefile mason_packages/headers/boost test/unique_ptr_test.cpp mkdir -p ./out - $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./ -pthreads $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -out/bench-variant: Makefile test/bench_variant.cpp variant.hpp recursive_wrapper.hpp +out/recursive_wrapper_test: Makefile mason_packages/headers/boost test/recursive_wrapper_test.cpp mkdir -p ./out - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -out/unique_ptr_test: Makefile test/unique_ptr_test.cpp variant.hpp recursive_wrapper.hpp +out/binary_visitor_test: Makefile mason_packages/headers/boost test/binary_visitor_test.cpp mkdir -p ./out - $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -out/recursive_wrapper_test: Makefile test/recursive_wrapper_test.cpp variant.hpp recursive_wrapper.hpp +out/lambda_overload_test: Makefile mason_packages/headers/boost test/lambda_overload_test.cpp mkdir -p ./out - $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + $(CXX) -o out/lambda_overload_test test/lambda_overload_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -out/binary_visitor_test: Makefile test/binary_visitor_test.cpp variant.hpp variant_io.hpp recursive_wrapper.hpp +out/hashable_test: Makefile mason_packages/headers/boost test/hashable_test.cpp mkdir -p ./out - $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) + $(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test ./out/bench-variant 100000 @@ -64,13 +93,13 @@ out/unit.o: Makefile test/unit.cpp mkdir -p ./out - $(CXX) -c -o $@ test/unit.cpp -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) + $(CXX) -c -o $@ test/unit.cpp -isystem test/include $(FINAL_CXXFLAGS) -out/%.o: test/t/%.cpp Makefile optional.hpp recursive_wrapper.hpp variant.hpp variant_io.hpp +out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS) mkdir -p ./out - $(CXX) -c -o $@ $< -I. -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) + $(CXX) -c -o $@ $< -Iinclude -isystem test/include $(FINAL_CXXFLAGS) -out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o +out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/issue122.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o mkdir -p ./out $(CXX) -o $@ $^ $(LDFLAGS) @@ -79,14 +108,14 @@ coverage: mkdir -p ./out - $(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./ -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) + $(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) -sizes: Makefile variant.hpp recursive_wrapper.hpp +sizes: Makefile mkdir -p ./out - @$(CXX) -o ./out/our_variant_hello_world.out variant.hpp $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world.out - @$(CXX) -o ./out/boost_variant_hello_world.out $(RUN_ARGS) $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world.out - @$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world - @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_variant_hello_world + @$(CXX) -o ./out/our_variant_hello_world.out include/mapbox/variant.hpp -I./include $(FINAL_CXXFLAGS) && du -h ./out/our_variant_hello_world.out + @$(CXX) -o ./out/boost_variant_hello_world.out $(BOOST_ROOT)/include/boost/variant.hpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world.out + @$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) && du -h ./out/our_variant_hello_world + @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world profile: out/bench-variant-debug mkdir -p profiling/ @@ -102,9 +131,9 @@ rm -f test/*gcov rm -f *.gcda *.gcno -pgo: out Makefile variant.hpp recursive_wrapper.hpp - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate +pgo: out Makefile + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -pg -fprofile-generate ./test-variant 500000 >/dev/null 2>/dev/null - $(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -fprofile-use + $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use .PHONY: sizes test diff -Nru mapbox-variant-1.1.0/optional.hpp mapbox-variant-1.1.5/optional.hpp --- mapbox-variant-1.1.0/optional.hpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/optional.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -#ifndef MAPBOX_UTIL_OPTIONAL_HPP -#define MAPBOX_UTIL_OPTIONAL_HPP - -#pragma message("This implementation of optional is deprecated. See https://github.com/mapbox/variant/issues/64.") - -#include -#include - -#include "variant.hpp" - -namespace mapbox { -namespace util { - -template -class optional -{ - static_assert(!std::is_reference::value, "optional doesn't support references"); - - struct none_type - { - }; - - variant 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 const& get() const { return variant_.template get(); } - T& get() { return variant_.template get(); } - - 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 - void emplace(Args&&... args) - { - variant_ = T{std::forward(args)...}; - } - - void reset() { variant_ = none_type{}; } - -}; // class optional - -} // namespace util -} // namespace mapbox - -#endif // MAPBOX_UTIL_OPTIONAL_HPP diff -Nru mapbox-variant-1.1.0/package.json mapbox-variant-1.1.5/package.json --- mapbox-variant-1.1.0/package.json 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/package.json 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,10 @@ +{ + "name": "variant", + "version": "1.3.0", + "description": "C++11/C++14 variant", + "main": "./package.json", + "repository" : { + "type" : "git", + "url" : "git://github.com/mapbox/variant.git" + } +} diff -Nru mapbox-variant-1.1.0/README.md mapbox-variant-1.1.5/README.md --- mapbox-variant-1.1.0/README.md 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/README.md 2017-01-08 19:20:43.000000000 +0000 @@ -1,11 +1,169 @@ # Mapbox Variant -An alternative to `boost::variant` for C++11. +An header-only alternative to `boost::variant` for C++11 and C++14 [![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant) [![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant) [![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master&service=github)](https://coveralls.io/r/mapbox/variant?branch=master) +## Introduction + +Variant's basic building blocks are: +- `variant` - a type-safe representation for sum-types / discriminated unions +- `recursive_wrapper` - a helper type to represent recursive "tree-like" variants +- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type +- `get()` - a function to directly unwrap a variant's underlying type +- `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant + + +### Basic Usage - HTTP API Example + +Suppose you want to represent a HTTP API response which is either a JSON result or an error: + +```c++ +struct Result { + Json object; +}; + +struct Error { + int32_t code; + string message; +}; +``` + +You can represent this at type level using a variant which is either an `Error` or a `Result`: + +```c++ +using Response = variant; + +Response makeRequest() { + return Error{501, "Not Implemented"}; +} + +Response ret = makeRequest(); +``` + +To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value: + +```c++ +ret.match([] (Result r) { print(r.object); }, + [] (Error e) { print(e.message); }); +``` + +Instead of using the variant's convenience `.match` pattern matching function you can create a type visitor functor and use `apply_visitor` manually: + +```c++ +struct ResponseVisitor { + void operator()(Result r) const { + print(r.object); + } + + void operator()(Error e) const { + print(e.message); + } +}; + +ResponseVisitor visitor; +apply_visitor(visitor, ret); +``` + +In both cases the compiler makes sure you handle all types the variant can represent at compile. + + +### Recursive Variants - JSON Example + +[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`. + + +```c++ +struct String { string value; }; +struct Number { double value; }; +struct True { }; +struct False { }; +struct Null { }; +struct Array { vector values; }; +struct Object { unordered_map values; }; +``` + +This works for primitive types but how do we represent recursive types such as `Array` which can hold multiple elements and `Array` itself, too? + +For these use cases Variant provides a `recursive_wrapper` helper type which lets you express recursive Variants. + +```c++ +struct String { string value; }; +struct Number { double value; }; +struct True { }; +struct False { }; +struct Null { }; + +// Forward declarations only +struct Array; +struct Object; + +using Value = variant, recursive_wrapper>; + +struct Array { + vector values; +}; + +struct Object { + unordered_map values; +}; +``` + +For walkig the JSON representation you can again either create a `JSONVisitor`: + +```c++ +struct JSONVisitor { + + void operator()(Null) const { + print("null"); + } + + // same for all other JSON types +}; + +JSONVisitor visitor; +apply_visitor(visitor, json); +``` + +Or use the convenience `.match` pattern matching function: + +```c++ +json.match([] (Null) { print("null"); }, + ...); +``` + +To summarize: use `recursive_wrapper` to represent recursive "tree-like" representations: + +```c++ +struct Empty { }; +struct Node; + +using Tree = variant>; + +struct Node { + uint64_t value; +} +``` +### Advanced Usage Tips + +Creating type aliases for variants is a great way to reduce repetition. +Keep in mind those type aliases are not checked at type level, though. +We recommend creating a new type for all but basic variant usage: + +```c++ +// the compiler can't tell the following two apart +using APIResult = variant; +using FilesystemResult = variant; + +// new type +struct APIResult : variant { + using Base = variant; + using Base::Base; +} +``` + ## Why use Mapbox Variant? @@ -45,6 +203,9 @@ Want to know more about the upcoming standard? Have a look at our [overview](doc/standards_effort.md). +Most modern high-level languages provide ways to express sum types directly. +If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums. + ## Depends @@ -55,19 +216,14 @@ - g++-4.7 - g++-4.8 - g++-4.9 - - g++-5 + - g++-5.2 - clang++-3.5 - clang++-3.6 - clang++-3.7 - clang++-3.8 + - clang++-3.9 - Visual Studio 2015 -## Usage - -There is nothing to build, just include `variant.hpp` and -`recursive_wrapper.hpp` in your project. Include `variant_io.hpp` if you need -the `operator<<` overload for variant. - ## Unit Tests @@ -93,15 +249,6 @@ ## Benchmarks -The benchmarks depend on: - - - Boost headers (for benchmarking against `boost::variant`) - - Boost built with `--with-timer` (used for benchmark timing) - -On Unix systems set your boost includes and libs locations and run `make test`: - - export LDFLAGS='-L/opt/boost/lib' - export CXXFLAGS='-I/opt/boost/include' make bench diff -Nru mapbox-variant-1.1.0/recursive_wrapper.hpp mapbox-variant-1.1.5/recursive_wrapper.hpp --- mapbox-variant-1.1.0/recursive_wrapper.hpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/recursive_wrapper.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP -#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP - -// Based on variant/recursive_wrapper.hpp from boost. -// -// Original license: -// -// Copyright (c) 2002-2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace mapbox { -namespace util { - -template -class recursive_wrapper -{ - - T* p_; - - void assign(T const& rhs) - { - this->get() = rhs; - } - - public: - using type = T; - - /** - * Default constructor default initializes the internally stored value. - * For POD types this means nothing is done and the storage is - * uninitialized. - * - * @throws std::bad_alloc if there is insufficient memory for an object - * of type T. - * @throws any exception thrown by the default constructur of T. - */ - recursive_wrapper() - : p_(new T){}; - - ~recursive_wrapper() noexcept { delete p_; }; - - recursive_wrapper(recursive_wrapper const& operand) - : p_(new T(operand.get())) {} - - recursive_wrapper(T const& operand) - : p_(new T(operand)) {} - - recursive_wrapper(recursive_wrapper&& operand) - : p_(new T(std::move(operand.get()))) {} - - recursive_wrapper(T&& operand) - : p_(new T(std::move(operand))) {} - - 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; - } - - T& get() - { - assert(p_); - return *get_pointer(); - } - - T const& get() const - { - assert(p_); - 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(); } - -}; // class recursive_wrapper - -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept -{ - lhs.swap(rhs); -} -} // namespace util -} // namespace mapbox - -#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP diff -Nru mapbox-variant-1.1.0/scripts/run_compilation_failure_tests.sh mapbox-variant-1.1.5/scripts/run_compilation_failure_tests.sh --- mapbox-variant-1.1.0/scripts/run_compilation_failure_tests.sh 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/scripts/run_compilation_failure_tests.sh 2017-01-08 19:20:43.000000000 +0000 @@ -14,7 +14,7 @@ error_msg() { if [ ! -z "$1" ]; then - printf 'output was:\n=======\n%s\n=======\n' "$1" + printf 'output was:\n=======\n%s\n=======\n' "$1" fi } @@ -22,29 +22,28 @@ for test_code in $DIR/*.cpp; do name=`basename $test_code .cpp` - result=`${CXX} -std=c++11 -c -o /dev/null -I. ${CXXFLAGS} ${test_code} 2>&1` + result=`${CXX} -std=c++11 -c -o /dev/null -I./include ${CXXFLAGS} ${test_code} 2>&1` status=$? if [ $status = 1 ]; then - expected=`sed -n -e '/@EXPECTED/s/.*: \+//p' ${test_code}` - if echo $result | grep -q "$expected"; then - echo "$name [OK]" - else - echo "$name [FAILED - wrong error message]" - echo "Expected error message: $expected" - error_msg "$result" - exit_code=1 - fi + expected=`sed -n -e '/@EXPECTED/s/.*: \+//p' ${test_code}` + if echo $result | grep -q "$expected"; then + echo "$name [OK]" + else + echo "$name [FAILED - wrong error message]" + echo "Expected error message: $expected" + error_msg "$result" + exit_code=1 + fi elif [ $status = 0 ]; then - echo "$name [FAILED - compile was successful]" - error_msg "$result" - exit_code=1 + echo "$name [FAILED - compile was successful]" + error_msg "$result" + exit_code=1 else - echo "$name [FAILED - unknown error in compile]" - error_msg "$result" - exit_code=1 + echo "$name [FAILED - unknown error in compile]" + error_msg "$result" + exit_code=1 fi done exit ${exit_code} - diff -Nru mapbox-variant-1.1.0/test/bench_variant.cpp mapbox-variant-1.1.5/test/bench_variant.cpp --- mapbox-variant-1.1.0/test/bench_variant.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/bench_variant.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,4 +1,3 @@ - #include #include #include @@ -8,10 +7,10 @@ #include #include -#include -#include +#include "auto_cpu_timer.hpp" -#include "variant.hpp" +#include +#include #define TEXT_SHORT "Test" #define TEXT_LONG "Testing various variant implementations with a longish string ........................................." @@ -140,12 +139,12 @@ { std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer t; + auto_cpu_timer t; run_variant_test(NUM_RUNS); } { std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer t; + auto_cpu_timer t; run_boost_test(NUM_RUNS); } } @@ -158,7 +157,7 @@ typedef thread_group::value_type value_type; thread_group tg; std::cerr << "custom variant: "; - boost::timer::auto_cpu_timer timer; + auto_cpu_timer timer; for (std::size_t i = 0; i < THREADS; ++i) { tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS)); @@ -171,7 +170,7 @@ typedef thread_group::value_type value_type; thread_group tg; std::cerr << "boost variant: "; - boost::timer::auto_cpu_timer timer; + auto_cpu_timer timer; for (std::size_t i = 0; i < THREADS; ++i) { tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS)); diff -Nru mapbox-variant-1.1.0/test/binary_visitor_test.cpp mapbox-variant-1.1.5/test/binary_visitor_test.cpp --- mapbox-variant-1.1.0/test/binary_visitor_test.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/binary_visitor_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -9,8 +9,8 @@ #include #include -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include using namespace mapbox; diff -Nru mapbox-variant-1.1.0/test/compilation_failure/default_constructor.cpp mapbox-variant-1.1.5/test/compilation_failure/default_constructor.cpp --- mapbox-variant-1.1.0/test/compilation_failure/default_constructor.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/default_constructor.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: First type in variant must be default constructible to allow default construction of variant -#include +#include // Checks that the first type in a variant must be default constructible to // make the variant default constructible. diff -Nru mapbox-variant-1.1.0/test/compilation_failure/empty_typelist.cpp mapbox-variant-1.1.5/test/compilation_failure/empty_typelist.cpp --- mapbox-variant-1.1.0/test/compilation_failure/empty_typelist.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/empty_typelist.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: Template parameter type list of variant can not be empty -#include +#include // Empty type list should not work. diff -Nru mapbox-variant-1.1.0/test/compilation_failure/equality.cpp mapbox-variant-1.1.5/test/compilation_failure/equality.cpp --- mapbox-variant-1.1.0/test/compilation_failure/equality.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/equality.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: -#include +#include int main() { diff -Nru mapbox-variant-1.1.0/test/compilation_failure/get_type.cpp mapbox-variant-1.1.5/test/compilation_failure/get_type.cpp --- mapbox-variant-1.1.0/test/compilation_failure/get_type.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/get_type.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: enable_if -#include +#include int main() { diff -Nru mapbox-variant-1.1.0/test/compilation_failure/is_type.cpp mapbox-variant-1.1.5/test/compilation_failure/is_type.cpp --- mapbox-variant-1.1.0/test/compilation_failure/is_type.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/is_type.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ +// @EXPECTED: -// @EXPECTED: invalid type in T in `is()` for this variant - -#include +#include int main() { diff -Nru mapbox-variant-1.1.0/test/compilation_failure/mutating_visitor_on_const.cpp mapbox-variant-1.1.5/test/compilation_failure/mutating_visitor_on_const.cpp --- mapbox-variant-1.1.0/test/compilation_failure/mutating_visitor_on_const.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/mutating_visitor_on_const.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: const int -#include +#include struct mutating_visitor { diff -Nru mapbox-variant-1.1.0/test/compilation_failure/no-reference.cpp mapbox-variant-1.1.5/test/compilation_failure/no-reference.cpp --- mapbox-variant-1.1.0/test/compilation_failure/no-reference.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/compilation_failure/no-reference.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,6 @@ - // @EXPECTED: Variant can not hold reference types -#include +#include int main() { diff -Nru mapbox-variant-1.1.0/test/hashable_test.cpp mapbox-variant-1.1.5/test/hashable_test.cpp --- mapbox-variant-1.1.0/test/hashable_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/test/hashable_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace mapbox::util; + +void test_singleton() +{ + using V = variant; + + V singleton = 5; + + if (std::hash{}(singleton) != std::hash{}(5)) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } +} + +void test_default_hashable() +{ + using V = variant; + + V var; + + // Check int hashes + var = 1; + + if (std::hash{}(var) != std::hash{}(1)) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } + + // Check double hashes + var = 23.4; + + if (std::hash{}(var) != std::hash{}(23.4)) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } + + // Check string hashes + var = std::string{"Hello, World!"}; + + if (std::hash{}(var) != std::hash{}("Hello, World!")) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } +} + +struct Hashable +{ + static const constexpr auto const_hash = 5; +}; + +namespace std { +template <> +struct hash +{ + std::size_t operator()(const Hashable&) const noexcept + { + return Hashable::const_hash; + } +}; +} + +void test_custom_hasher() +{ + using V = variant; + + V var; + + var = Hashable{}; + + if (std::hash{}(var) != Hashable::const_hash) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } +} + +void test_hashable_in_container() +{ + using V = variant; + + // won't compile if V is not Hashable + std::unordered_set vs; + + vs.insert(1); + vs.insert(2.3); + vs.insert("4"); +} + +struct Empty +{ +}; + +struct Node; + +using Tree = variant>; + +struct Node +{ + Node(Tree left_, Tree right_) : left(std::move(left_)), right(std::move(right_)) {} + + Tree left = Empty{}; + Tree right = Empty{}; +}; + +namespace std { +template <> +struct hash +{ + std::size_t operator()(const Empty&) const noexcept + { + return 3; + } +}; + +template <> +struct hash +{ + std::size_t operator()(const Node& n) const noexcept + { + return 5 + std::hash{}(n.left) + std::hash{}(n.right); + } +}; +} + +void test_recursive_hashable() +{ + + Tree tree = Node{Node{Empty{}, Empty{}}, Empty{}}; + + if (std::hash{}(tree) != ((5 + (5 + (3 + 3))) + 3)) + { + std::cerr << "Expected variant hash to be the same as hash of its value\n"; + std::exit(EXIT_FAILURE); + } +} + +int main() +{ + test_singleton(); + test_default_hashable(); + test_custom_hasher(); + test_hashable_in_container(); + test_recursive_hashable(); +} diff -Nru mapbox-variant-1.1.0/test/include/auto_cpu_timer.hpp mapbox-variant-1.1.5/test/include/auto_cpu_timer.hpp --- mapbox-variant-1.1.0/test/include/auto_cpu_timer.hpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/test/include/auto_cpu_timer.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +struct auto_cpu_timer { + std::chrono::time_point start; + auto_cpu_timer() : start(std::chrono::high_resolution_clock::now()) { + } + ~auto_cpu_timer() { + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::microseconds elapsed = + std::chrono::duration_cast(end - start); + std::cerr << elapsed.count() << "us" << std::endl; + } +}; diff -Nru mapbox-variant-1.1.0/test/lambda_overload_test.cpp mapbox-variant-1.1.5/test/lambda_overload_test.cpp --- mapbox-variant-1.1.0/test/lambda_overload_test.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/test/lambda_overload_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,127 @@ +#include +#include + +#include +#include + +#if __cplusplus >= 201402L +#define HAS_CPP14_SUPPORT +#endif + +using namespace mapbox::util; + +template +using Either = mapbox::util::variant; + +struct Response +{ +}; + +struct Error +{ +}; + +void test_lambda_overloads() +{ + Either rv; + + rv = Response{}; + + auto visitor = make_visitor([](Response) { std::cout << "Response\n"; }, // + [](Error) { std::cout << "Error\n"; }); // + apply_visitor(visitor, rv); +} + +void test_lambda_overloads_capture() +{ + Either rv; + + rv = Error{}; + + int ok = 0; + int err = 0; + + auto visitor = make_visitor([&](Response) { ok += 1; }, // + [&](Error) { err += 1; }); // + apply_visitor(visitor, rv); + + std::cout << "Got " << ok << " ok, " << err << " err" << std::endl; +} + +void test_singleton_variant() +{ + + variant singleton; + apply_visitor(make_visitor([](int) {}), singleton); +} + +void test_lambda_overloads_sfinae() +#ifdef HAS_CPP14_SUPPORT +{ + variant> var; + + auto visitor = make_visitor([](auto range) -> decltype(std::begin(range), void()) { + for (auto each : range) + std::cout << each << ' '; }, + [](auto x) -> decltype(std::cout << x, void()) { + std::cout << x << std::endl; + }); + + var = 1; + apply_visitor(visitor, var); + + var = 2.f; + apply_visitor(visitor, var); + + var = std::vector{4, 5, 6}; + apply_visitor(visitor, var); +} +#else +{ +} +#endif + +void test_match_singleton() +{ + variant singleton = 5; + singleton.match([](int) {}); +} + +void test_match_overloads() +{ + Either rv; + + rv = Response{}; + + rv.match([](Response) { std::cout << "Response\n"; }, // + [](Error) { std::cout << "Error\n"; }); // +} + +void test_match_overloads_capture() +{ + Either rv; + + rv = Error{}; + + int ok = 0; + int err = 0; + + rv.match([&](Response) { ok += 1; }, // + [&](Error) { err += 1; }); // + + std::cout << "Got " << ok << " ok, " << err << " err" << std::endl; +} + +int main() +{ + test_lambda_overloads(); + test_singleton_variant(); + test_lambda_overloads_capture(); + test_lambda_overloads_sfinae(); + + test_match_singleton(); + test_match_overloads(); + test_match_overloads_capture(); +} + +#undef HAS_CPP14_SUPPORT diff -Nru mapbox-variant-1.1.0/test/our_variant_hello_world.cpp mapbox-variant-1.1.5/test/our_variant_hello_world.cpp --- mapbox-variant-1.1.0/test/our_variant_hello_world.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/our_variant_hello_world.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,4 +1,4 @@ -#include "variant.hpp" +#include #include diff -Nru mapbox-variant-1.1.0/test/recursive_wrapper_test.cpp mapbox-variant-1.1.5/test/recursive_wrapper_test.cpp --- mapbox-variant-1.1.0/test/recursive_wrapper_test.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/recursive_wrapper_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -5,9 +5,9 @@ #include #include -#include +#include "auto_cpu_timer.hpp" -#include "variant.hpp" +#include using namespace mapbox; @@ -111,7 +111,7 @@ int total = 0; { - boost::timer::auto_cpu_timer t; + auto_cpu_timer t; for (std::size_t i = 0; i < NUM_ITER; ++i) { total += util::apply_visitor(test::calculator(), result); diff -Nru mapbox-variant-1.1.0/test/reference_wrapper_test.cpp mapbox-variant-1.1.5/test/reference_wrapper_test.cpp --- mapbox-variant-1.1.0/test/reference_wrapper_test.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/reference_wrapper_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -6,7 +6,7 @@ #include #include -#include "variant.hpp" +#include using namespace mapbox; @@ -41,9 +41,12 @@ void operator()(line_string const& line) const { std::cerr << "Line("; + bool first = true; for (auto const& pt : line) { - std::cerr << pt.x << " " << pt.y << ","; + if (!first) std::cerr << ","; + std::cerr << pt.x << " " << pt.y; + if (first) first = false; } std::cerr << ")" << std::endl; } diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_1.cpp mapbox-variant-1.1.5/test/t/binary_visitor_1.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_1.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_1.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " i-d" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_2.cpp mapbox-variant-1.1.5/test/t/binary_visitor_2.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_2.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_2.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " b-i-d" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_3.cpp mapbox-variant-1.1.5/test/t/binary_visitor_3.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_3.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_3.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " i-d-b" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_4.cpp mapbox-variant-1.1.5/test/t/binary_visitor_4.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_4.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_4.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " b-i-d-c" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_5.cpp mapbox-variant-1.1.5/test/t/binary_visitor_5.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_5.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_5.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " b-i-c-d-i" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_6.cpp mapbox-variant-1.1.5/test/t/binary_visitor_6.cpp --- mapbox-variant-1.1.0/test/t/binary_visitor_6.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_6.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,5 +1,5 @@ -#include "variant.hpp" +#include #define NAME_EXT " b-i-i-d-c-u" using variant_type = mapbox::util::variant; diff -Nru mapbox-variant-1.1.0/test/t/binary_visitor_impl.hpp mapbox-variant-1.1.5/test/t/binary_visitor_impl.hpp --- mapbox-variant-1.1.0/test/t/binary_visitor_impl.hpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/binary_visitor_impl.hpp 2017-01-08 19:20:43.000000000 +0000 @@ -3,7 +3,7 @@ #include "catch.hpp" -#include "variant_io.hpp" +#include struct add_visitor { @@ -160,8 +160,8 @@ { using T = typename std::common_type::type; T tmp = a; - a = b; - b = tmp; + a = static_cast(b); + b = static_cast(tmp); } }; diff -Nru mapbox-variant-1.1.0/test/t/issue122.cpp mapbox-variant-1.1.5/test/t/issue122.cpp --- mapbox-variant-1.1.0/test/t/issue122.cpp 1970-01-01 00:00:00.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/issue122.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -0,0 +1,20 @@ +#include "catch.hpp" + +#include +#include + +// https://github.com/mapbox/variant/issues/122 + +struct X +{ + template + X(const ValueType&) {} +}; + + +TEST_CASE("Correctly choose appropriate constructor", "[variant]") +{ + mapbox::util::variant a{123}; + decltype(a) b(a); + REQUIRE(a.which() == b.which()); +} diff -Nru mapbox-variant-1.1.0/test/t/issue21.cpp mapbox-variant-1.1.5/test/t/issue21.cpp --- mapbox-variant-1.1.0/test/t/issue21.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/issue21.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,8 +1,7 @@ - #include "catch.hpp" -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include // https://github.com/mapbox/variant/issues/21 @@ -11,6 +10,12 @@ struct t1 { int value; + + t1(t1 const& rhs) + : value(rhs.value) + { + ++count; + } t1(int v) : value(v) { ++count; @@ -37,7 +42,8 @@ count = 0; { - variant_type v{42}; + t1 obj{42}; + variant_type v = obj; REQUIRE(v.is()); REQUIRE(v.get().value == 42); REQUIRE_THROWS({ diff -Nru mapbox-variant-1.1.0/test/t/mutating_visitor.cpp mapbox-variant-1.1.5/test/t/mutating_visitor.cpp --- mapbox-variant-1.1.0/test/t/mutating_visitor.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/mutating_visitor.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,8 +1,8 @@ #include "catch.hpp" -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include #include diff -Nru mapbox-variant-1.1.0/test/t/optional.cpp mapbox-variant-1.1.5/test/t/optional.cpp --- mapbox-variant-1.1.0/test/t/optional.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/optional.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,7 @@ #include "catch.hpp" -#include "optional.hpp" +#include struct dummy { diff -Nru mapbox-variant-1.1.0/test/t/recursive_wrapper.cpp mapbox-variant-1.1.5/test/t/recursive_wrapper.cpp --- mapbox-variant-1.1.0/test/t/recursive_wrapper.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/recursive_wrapper.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,7 @@ #include "catch.hpp" -#include "recursive_wrapper.hpp" +#include #include #include diff -Nru mapbox-variant-1.1.0/test/t/sizeof.cpp mapbox-variant-1.1.5/test/t/sizeof.cpp --- mapbox-variant-1.1.0/test/t/sizeof.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/sizeof.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -5,8 +5,8 @@ #include "catch.hpp" -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include struct some_struct { diff -Nru mapbox-variant-1.1.0/test/t/unary_visitor.cpp mapbox-variant-1.1.5/test/t/unary_visitor.cpp --- mapbox-variant-1.1.0/test/t/unary_visitor.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/unary_visitor.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,8 +1,8 @@ #include "catch.hpp" -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include #include diff -Nru mapbox-variant-1.1.0/test/t/variant.cpp mapbox-variant-1.1.5/test/t/variant.cpp --- mapbox-variant-1.1.0/test/t/variant.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/t/variant.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -1,7 +1,7 @@ #include "catch.hpp" -#include "variant.hpp" -#include "variant_io.hpp" +#include +#include #include #include @@ -325,7 +325,7 @@ TEST_CASE("implicit conversion to first type in variant type list", "[variant][implicit conversion]") { using variant_type = mapbox::util::variant; - variant_type var = 5.0; // converted to long + variant_type var = 5l; // converted to long REQUIRE(var.get() == 5); REQUIRE_THROWS_AS({ var.get(); @@ -543,9 +543,9 @@ int a = 1; variant_type v{std::cref(a)}; REQUIRE(v.get() == 1); - REQUIRE(v.get() == 1); // this works (see #82) + REQUIRE(v.get() == 1); REQUIRE(mapbox::util::get(v) == 1); - // REQUIRE(mapbox::util::get(v) == 1); // this doesn't work (see #82) + REQUIRE(mapbox::util::get(v) == 1); REQUIRE_THROWS_AS({ v.get(); }, @@ -568,3 +568,26 @@ }, mapbox::util::bad_variant_access&); } + +TEST_CASE("recursive wrapper") +{ + using variant_type = mapbox::util::variant>; + variant_type v(1); + REQUIRE(v.is()); + REQUIRE(v.get() == 1); +} + + +TEST_CASE("variant : direct_type helper should match T, references (T&) and const references (T const&) to the original type T)") +{ + using value = mapbox::util::variant; + + std::uint64_t u(1234); + REQUIRE(value(u).is()); // matches T + + std::uint64_t& ur(u); + REQUIRE(value(ur).is()); // matches T& + + std::uint64_t const& ucr(u); + REQUIRE(value(ucr).is()); // matches T const& +} diff -Nru mapbox-variant-1.1.0/test/unique_ptr_test.cpp mapbox-variant-1.1.5/test/unique_ptr_test.cpp --- mapbox-variant-1.1.0/test/unique_ptr_test.cpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/test/unique_ptr_test.cpp 2017-01-08 19:20:43.000000000 +0000 @@ -6,9 +6,9 @@ #include #include -#include +#include "auto_cpu_timer.hpp" -#include "variant.hpp" +#include using namespace mapbox; @@ -112,7 +112,7 @@ int total = 0; { - boost::timer::auto_cpu_timer t; + auto_cpu_timer t; for (std::size_t i = 0; i < NUM_ITER; ++i) { total += util::apply_visitor(test::calculator(), result); diff -Nru mapbox-variant-1.1.0/.travis.yml mapbox-variant-1.1.5/.travis.yml --- mapbox-variant-1.1.0/.travis.yml 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/.travis.yml 2017-01-08 19:20:43.000000000 +0000 @@ -1,127 +1,170 @@ -language: c +language: generic sudo: false -# Save common build configurations as shortcuts, so we can reference them later. -addons_shortcuts: - addons_clang35: &clang35 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5', 'boost-latest' ] - packages: [ 'clang-3.5', 'libboost1.55-all-dev' ] - addons_clang36: &clang36 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'boost-latest' ] - packages: [ 'clang-3.6', 'libboost1.55-all-dev' ] - addons_clang37: &clang37 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7', 'boost-latest' ] - packages: [ 'clang-3.7', 'libboost1.55-all-dev' ] - addons_clang38: &clang38 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise', 'boost-latest' ] - packages: [ 'clang-3.8', 'libboost1.55-all-dev'] - addons_gcc47: &gcc47 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] - packages: [ 'g++-4.7', 'libboost1.55-all-dev' ] - addons_gcc48: &gcc48 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] - packages: [ 'g++-4.8', 'libboost1.55-all-dev' ] - addons_gcc49: &gcc49 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] - packages: [ 'g++-4.9', 'libboost1.55-all-dev' ] - addons_gcc5: &gcc5 - apt: - sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] - packages: [ 'g++-5', 'libboost1.55-all-dev' ] - matrix: include: + # clang++ 3.9 via mason with -flto and -fsanitize=cfi + - os: linux + compiler: "clang++-39-mason" + env: CXX=clang++-3.9 CXXFLAGS="-flto -fsanitize=cfi -fvisibility=hidden" LDFLAGS="-flto -fsanitize=cfi -fvisibility=hidden" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_install: + - git submodule update --init + - ./.mason/mason install clang++ 3.9.1 + - export PATH=$(./.mason/mason prefix clang++ 3.9.1)/bin:${PATH} + - ./.mason/mason install binutils 2.27 + - export PATH=$(./.mason/mason prefix binutils 2.27)/bin:${PATH} + # clang++ 3.9 via mason with -fsanitize=address + - os: linux + compiler: "clang++-39-mason" + env: CXX=clang++-3.9 CXXFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common" LDFLAGS="-fsanitize=address" ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_install: + - git submodule update --init + - ./.mason/mason install clang++ 3.9.1 + - export PATH=$(./.mason/mason prefix clang++ 3.9.1)/bin:${PATH} + # clang++ 3.9 via mason with -fsanitize=undefined + - os: linux + compiler: "clang++-39-mason" + env: CXX=clang++-3.9 CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_install: + - git submodule update --init + - ./.mason/mason install clang++ 3.9.1 + - export PATH=$(./.mason/mason prefix clang++ 3.9.1)/bin:${PATH} + # clang++ 3.9 via mason with -fsanitize=integer + - os: linux + compiler: "clang++-39-mason" + env: CXX=clang++-3.9 CXXFLAGS="-fsanitize=integer" LDFLAGS="-fsanitize=integer" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_install: + - git submodule update --init + - ./.mason/mason install clang++ 3.9.1 + - export PATH=$(./.mason/mason prefix clang++ 3.9.1)/bin:${PATH} + # clang++ 3.9 via mason with -fsanitize=safe-stack + - os: linux + compiler: "clang++-39-mason" + env: CXX=clang++-3.9 CXXFLAGS="-fsanitize=safe-stack" LDFLAGS="-fsanitize=safe-stack" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_install: + - git submodule update --init + - ./.mason/mason install clang++ 3.9.1 + - export PATH=$(./.mason/mason prefix clang++ 3.9.1)/bin:${PATH} - os: osx - osx_image: xcode6 + osx_image: xcode8 + env: OSX_OLDEST_SUPPORTED=10.7 TEST_GYP_BUILD=True compiler: clang - os: osx - osx_image: xcode7 - env: TEST_GYP_BUILD=True + osx_image: xcode8 + env: OSX_OLDEST_SUPPORTED=10.12 compiler: clang - os: linux compiler: "clang35" - env: CXX=clang++-3.5 - addons: *clang35 + env: CXX=clang++-3.5 COVERAGE=True + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] + packages: [ 'clang-3.5', 'libstdc++-4.9-dev' ] - os: linux compiler: "clang36" env: CXX=clang++-3.6 - addons: *clang36 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ] + packages: [ 'clang-3.6' ] - os: linux compiler: "clang37" - env: CXX=clang++-3.7 COVERAGE=True - addons: *clang37 - - os: linux - compiler: "clang38" - env: CXX=clang++-3.8 - addons: *clang38 - - os: linux - compiler: "clang38" - env: CXX=clang++-3.8 CXX_STD=c++14 - addons: *clang38 + env: CXX=clang++-3.7 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7' ] + packages: [ 'clang-3.7' ] - os: linux compiler: "gcc47" - env: CXX=g++-4.7 - addons: *gcc47 + env: CXX=g++-4.7 CXXFLAGS="-Wno-parentheses" + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-4.7' ] - os: linux compiler: "gcc48" env: CXX=g++-4.8 - addons: *gcc48 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-4.8' ] - os: linux compiler: "gcc49" env: CXX=g++-4.9 - addons: *gcc49 - - os: linux - compiler: "gcc49" - env: CXX=g++-4.9 CXX_STD=c++14 - addons: *gcc49 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-4.9' ] - os: linux compiler: "gcc5" - env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" - addons: *gcc5 - - os: linux - compiler: "gcc5" - env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1" - addons: *gcc5 + env: CXX=g++-5 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-5' ] + - os: linux + compiler: "gcc6" + env: CXX=g++-6 CXX_STD=c++14 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-6' ] -before_install: +install: - echo ${CXX} - if [[ $(uname -s) == 'Linux' ]]; then export PYTHONPATH=$(pwd)/.local/lib/python2.7/site-packages; else - brew install boost; export PYTHONPATH=$(pwd)/.local/lib/python/site-packages; fi - if [[ ${COVERAGE:-0} == 'True' ]]; then PYTHONUSERBASE=$(pwd)/.local pip install --user cpp-coveralls; fi -install: +script: + # Build in Release - make test - make bench - - if [[ $(uname -s) == 'Linux' ]]; then - make sizes /usr/include/boost/variant.hpp; - else - make sizes `brew --prefix`/include/boost/variant.hpp; - fi + - make sizes + - scripts/run_compilation_failure_tests.sh + - make clean; + # Build in Debug + - export BUILDTYPE=Debug + - make test + - make bench + - make sizes - scripts/run_compilation_failure_tests.sh - if [[ ${TEST_GYP_BUILD:-0} == 'True' ]]; then make clean; make gyp; fi -script: +after_script: - if [[ ${COVERAGE:-0} == 'True' ]]; then make clean; make coverage; ./out/cov-test; cp unit*gc* test/; - ./.local/bin/cpp-coveralls -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp --gcov-options '\-lp'; + ./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp; fi diff -Nru mapbox-variant-1.1.0/variant.gyp mapbox-variant-1.1.5/variant.gyp --- mapbox-variant-1.1.0/variant.gyp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/variant.gyp 2017-01-08 19:20:43.000000000 +0000 @@ -27,7 +27,7 @@ "SUPPORTED_PLATFORMS":["macosx"] }, "include_dirs": [ - "./", + "./include", "test/include" ] } diff -Nru mapbox-variant-1.1.0/variant.hpp mapbox-variant-1.1.5/variant.hpp --- mapbox-variant-1.1.0/variant.hpp 2016-02-11 09:28:18.000000000 +0000 +++ mapbox-variant-1.1.5/variant.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,901 +0,0 @@ -#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 "recursive_wrapper.hpp" - -// 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 - -#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; -}; - -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 -{ - using value_type = typename std::remove_reference::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; -}; - -// check if T is in Types... -template -struct has_type; - -template -struct has_type -{ - static constexpr bool value = std::is_same::value || has_type::value; -}; - -template -struct has_type : std::false_type -{ -}; - -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 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())); - } - 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())); - } - 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())); - } - - VARIANT_INLINE static R apply(V& v, F&& f) - { - return f(unwrapper::apply(v.template get())); - } -}; - -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()), - unwrapper::apply_const(rhs.template get())); - } - 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()), - unwrapper::apply(rhs.template get())); - } - 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()), - unwrapper::apply_const(rhs.template get())); - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - return f(unwrapper::apply(lhs.template get()), - unwrapper::apply(rhs.template get())); - } -}; - -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()), - unwrapper::apply_const(rhs.template get())); - } - 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()), - unwrapper::apply(rhs.template get())); - } - 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()), - unwrapper::apply_const(rhs.template get())); - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - return f(unwrapper::apply(lhs.template get()), - unwrapper::apply(rhs.template get())); - } -}; - -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()), - unwrapper::apply_const(v1.template get())); // 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()), - unwrapper::apply(v1.template get())); // 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()), - unwrapper::apply_const(v1.template get())); // call binary functor - } - - VARIANT_INLINE static R apply(V& v0, V& v1, F&& f) - { - return f(unwrapper::apply(v0.template get()), - unwrapper::apply(v1.template get())); // 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(); - return Comp()(lhs_content, rhs_content); - } - - private: - Variant const& lhs_; -}; - -// True if Predicate matches for all of the types Ts -template