From 2983982bbeb15b87196d24f1adb35a8db02657dc Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 30 Mar 2020 20:58:00 -0700 Subject: [PATCH 01/42] Add varint files --- api/include/opentelemetry/nostd/in_place.hpp | 27 + api/include/opentelemetry/nostd/lib.hpp | 503 +++++ api/include/opentelemetry/nostd/variant.hpp | 2030 ++++++++++++++++++ 3 files changed, 2560 insertions(+) create mode 100644 api/include/opentelemetry/nostd/in_place.hpp create mode 100644 api/include/opentelemetry/nostd/lib.hpp create mode 100644 api/include/opentelemetry/nostd/variant.hpp diff --git a/api/include/opentelemetry/nostd/in_place.hpp b/api/include/opentelemetry/nostd/in_place.hpp new file mode 100644 index 0000000000..73a0cdaaad --- /dev/null +++ b/api/include/opentelemetry/nostd/in_place.hpp @@ -0,0 +1,27 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#pragma once + +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ + + struct in_place_t { explicit in_place_t() = default; }; + + template + struct in_place_index_t { explicit in_place_index_t() = default; }; + + template + struct in_place_type_t { explicit in_place_type_t() = default; }; + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/lib.hpp b/api/include/opentelemetry/nostd/lib.hpp new file mode 100644 index 0000000000..7ba94d6a73 --- /dev/null +++ b/api/include/opentelemetry/nostd/lib.hpp @@ -0,0 +1,503 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#ifndef MPARK_LIB_HPP +#define MPARK_LIB_HPP + +#include +#include +#include +#include + +#include "config.hpp" + +#define MPARK_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + +namespace mpark { + namespace lib { + template + struct identity { using type = T; }; + + inline namespace cpp14 { + template + struct array { + constexpr const T &operator[](std::size_t index) const { + return data[index]; + } + + T data[N == 0 ? 1 : N]; + }; + + template + using add_pointer_t = typename std::add_pointer::type; + + template + using common_type_t = typename std::common_type::type; + + template + using decay_t = typename std::decay::type; + + template + using enable_if_t = typename std::enable_if::type; + + template + using remove_const_t = typename std::remove_const::type; + + template + using remove_reference_t = typename std::remove_reference::type; + + template + using remove_cvref_t = + typename std::remove_cv>::type; + + template + inline constexpr T &&forward(remove_reference_t &t) noexcept { + return static_cast(t); + } + + template + inline constexpr T &&forward(remove_reference_t &&t) noexcept { + static_assert(!std::is_lvalue_reference::value, + "can not forward an rvalue as an lvalue"); + return static_cast(t); + } + + template + inline constexpr remove_reference_t &&move(T &&t) noexcept { + return static_cast &&>(t); + } + +#ifdef MPARK_INTEGER_SEQUENCE + using std::integer_sequence; + using std::index_sequence; + using std::make_index_sequence; + using std::index_sequence_for; +#else + template + struct integer_sequence { + using value_type = T; + static constexpr std::size_t size() noexcept { return sizeof...(Is); } + }; + + template + using index_sequence = integer_sequence; + + template + struct make_index_sequence_concat; + + template + struct make_index_sequence_concat, + index_sequence> + : identity> {}; + + template + struct make_index_sequence_impl; + + template + using make_index_sequence = typename make_index_sequence_impl::type; + + template + struct make_index_sequence_impl + : make_index_sequence_concat, + make_index_sequence> {}; + + template <> + struct make_index_sequence_impl<0> : identity> {}; + + template <> + struct make_index_sequence_impl<1> : identity> {}; + + template + using index_sequence_for = make_index_sequence; +#endif + + // +#ifdef MPARK_TRANSPARENT_OPERATORS + using equal_to = std::equal_to<>; +#else + struct equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using not_equal_to = std::not_equal_to<>; +#else + struct not_equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using less = std::less<>; +#else + struct less { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using greater = std::greater<>; +#else + struct greater { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using less_equal = std::less_equal<>; +#else + struct less_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using greater_equal = std::greater_equal<>; +#else + struct greater_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) + }; +#endif + } // namespace cpp14 + + inline namespace cpp17 { + + // + template + using bool_constant = std::integral_constant; + + template + struct voider : identity {}; + + template + using void_t = typename voider::type; + + namespace detail { + namespace swappable { + + using std::swap; + + template + struct is_swappable { + private: + template (), + std::declval()))> + inline static std::true_type test(int); + + template + inline static std::false_type test(...); + + public: + static constexpr bool value = decltype(test(0))::value; + }; + + template + struct is_nothrow_swappable { + static constexpr bool value = + noexcept(swap(std::declval(), std::declval())); + }; + + template + struct is_nothrow_swappable : std::false_type {}; + + } // namespace swappable + } // namespace detail + + using detail::swappable::is_swappable; + + template + using is_nothrow_swappable = + detail::swappable::is_nothrow_swappable::value, T>; + + // + namespace detail { + + template + struct is_reference_wrapper : std::false_type {}; + + template + struct is_reference_wrapper> + : std::true_type {}; + + template + struct Invoke; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) + }; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((lib::forward(arg).get().*pmf)(lib::forward(args)...)) + }; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN(((*lib::forward(arg)).*pmf)(lib::forward(args)...)) + }; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(lib::forward(arg).*pmo) + }; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(lib::forward(arg).get().*pmo) + }; + + template <> + struct Invoke { + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN((*lib::forward(arg)).*pmo) + }; + + template + inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) + MPARK_RETURN( + Invoke::value, + (std::is_base_of>::value + ? 0 + : is_reference_wrapper>::value + ? 1 + : 2)>::invoke(f, + lib::forward(arg), + lib::forward(args)...)) + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template + inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } // namespace detail + + template + inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(detail::invoke(lib::forward(f), + lib::forward(args)...)) + + namespace detail { + + template + struct invoke_result {}; + + template + struct invoke_result(), std::declval()...))>, + F, + Args...> + : identity(), std::declval()...))> {}; + + } // namespace detail + + template + using invoke_result = detail::invoke_result; + + template + using invoke_result_t = typename invoke_result::type; + + namespace detail { + + template + struct is_invocable : std::false_type {}; + + template + struct is_invocable>, F, Args...> + : std::true_type {}; + + template + struct is_invocable_r : std::false_type {}; + + template + struct is_invocable_r>, + R, + F, + Args...> + : std::is_convertible, R> {}; + + } // namespace detail + + template + using is_invocable = detail::is_invocable; + + template + using is_invocable_r = detail::is_invocable_r; + + // +#ifdef MPARK_BUILTIN_ADDRESSOF + template + inline constexpr T *addressof(T &arg) noexcept { + return __builtin_addressof(arg); + } +#else + namespace detail { + + namespace has_addressof_impl { + + struct fail; + + template + inline fail operator&(T &&); + + template + inline static constexpr bool impl() { + return (std::is_class::value || std::is_union::value) && + !std::is_same()), fail>::value; + } + + } // namespace has_addressof_impl + + template + using has_addressof = bool_constant()>; + + template + inline constexpr T *addressof(T &arg, std::true_type) noexcept { + return std::addressof(arg); + } + + template + inline constexpr T *addressof(T &arg, std::false_type) noexcept { + return &arg; + } + + } // namespace detail + + template + inline constexpr T *addressof(T &arg) noexcept { + return detail::addressof(arg, detail::has_addressof{}); + } +#endif + + template + inline constexpr T *addressof(const T &&) = delete; + + } // namespace cpp17 + + template + struct remove_all_extents : identity {}; + + template + struct remove_all_extents> : remove_all_extents {}; + + template + using remove_all_extents_t = typename remove_all_extents::type; + + template + using size_constant = std::integral_constant; + + template + struct indexed_type : size_constant { using type = T; }; + + template + using all = std::is_same, + integer_sequence>; + +#ifdef MPARK_TYPE_PACK_ELEMENT + template + using type_pack_element_t = __type_pack_element; +#else + template + struct type_pack_element_impl { + private: + template + struct set; + + template + struct set> : indexed_type... {}; + + template + inline static std::enable_if impl(indexed_type); + + inline static std::enable_if impl(...); + + public: + using type = decltype(impl(set>{})); + }; + + template + using type_pack_element = typename type_pack_element_impl::type; + + template + using type_pack_element_t = typename type_pack_element::type; +#endif + +#ifdef MPARK_TRIVIALITY_TYPE_TRAITS + using std::is_trivially_copy_constructible; + using std::is_trivially_move_constructible; + using std::is_trivially_copy_assignable; + using std::is_trivially_move_assignable; +#else + template + struct is_trivially_copy_constructible + : bool_constant< + std::is_copy_constructible::value && __has_trivial_copy(T)> {}; + + template + struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; + + template + struct is_trivially_copy_assignable + : bool_constant< + std::is_copy_assignable::value && __has_trivial_assign(T)> {}; + + template + struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; +#endif + + template + struct dependent_type : T {}; + + template + struct push_back; + + template + using push_back_t = typename push_back::type; + + template + struct push_back, J> { + using type = index_sequence; + }; + + } // namespace lib +} // namespace mpark + +#undef MPARK_RETURN + +#endif // MPARK_LIB_HPP diff --git a/api/include/opentelemetry/nostd/variant.hpp b/api/include/opentelemetry/nostd/variant.hpp new file mode 100644 index 0000000000..537d938813 --- /dev/null +++ b/api/include/opentelemetry/nostd/variant.hpp @@ -0,0 +1,2030 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#pragma once + +/* + variant synopsis + +namespace std { + + // 20.7.2, class template variant + template + class variant { + public: + + // 20.7.2.1, constructors + constexpr variant() noexcept(see below); + variant(const variant&); + variant(variant&&) noexcept(see below); + + template constexpr variant(T&&) noexcept(see below); + + template + constexpr explicit variant(in_place_type_t, Args&&...); + + template + constexpr explicit variant( + in_place_type_t, initializer_list, Args&&...); + + template + constexpr explicit variant(in_place_index_t, Args&&...); + + template + constexpr explicit variant( + in_place_index_t, initializer_list, Args&&...); + + // 20.7.2.2, destructor + ~variant(); + + // 20.7.2.3, assignment + variant& operator=(const variant&); + variant& operator=(variant&&) noexcept(see below); + + template variant& operator=(T&&) noexcept(see below); + + // 20.7.2.4, modifiers + template + T& emplace(Args&&...); + + template + T& emplace(initializer_list, Args&&...); + + template + variant_alternative& emplace(Args&&...); + + template + variant_alternative& emplace(initializer_list, Args&&...); + + // 20.7.2.5, value status + constexpr bool valueless_by_exception() const noexcept; + constexpr size_t index() const noexcept; + + // 20.7.2.6, swap + void swap(variant&) noexcept(see below); + }; + + // 20.7.3, variant helper classes + template struct variant_size; // undefined + + template + constexpr size_t variant_size_v = variant_size::value; + + template struct variant_size; + template struct variant_size; + template struct variant_size; + + template + struct variant_size>; + + template struct variant_alternative; // undefined + + template + using variant_alternative_t = typename variant_alternative::type; + + template struct variant_alternative; + template struct variant_alternative; + template struct variant_alternative; + + template + struct variant_alternative>; + + constexpr size_t variant_npos = -1; + + // 20.7.4, value access + template + constexpr bool holds_alternative(const variant&) noexcept; + + template + constexpr variant_alternative_t>& + get(variant&); + + template + constexpr variant_alternative_t>&& + get(variant&&); + + template + constexpr variant_alternative_t> const& + get(const variant&); + + template + constexpr variant_alternative_t> const&& + get(const variant&&); + + template + constexpr T& get(variant&); + + template + constexpr T&& get(variant&&); + + template + constexpr const T& get(const variant&); + + template + constexpr const T&& get(const variant&&); + + template + constexpr add_pointer_t>> + get_if(variant*) noexcept; + + template + constexpr add_pointer_t>> + get_if(const variant*) noexcept; + + template + constexpr add_pointer_t + get_if(variant*) noexcept; + + template + constexpr add_pointer_t + get_if(const variant*) noexcept; + + // 20.7.5, relational operators + template + constexpr bool operator==(const variant&, const variant&); + + template + constexpr bool operator!=(const variant&, const variant&); + + template + constexpr bool operator<(const variant&, const variant&); + + template + constexpr bool operator>(const variant&, const variant&); + + template + constexpr bool operator<=(const variant&, const variant&); + + template + constexpr bool operator>=(const variant&, const variant&); + + // 20.7.6, visitation + template + constexpr see below visit(Visitor&&, Variants&&...); + + // 20.7.7, class monostate + struct monostate; + + // 20.7.8, monostate relational operators + constexpr bool operator<(monostate, monostate) noexcept; + constexpr bool operator>(monostate, monostate) noexcept; + constexpr bool operator<=(monostate, monostate) noexcept; + constexpr bool operator>=(monostate, monostate) noexcept; + constexpr bool operator==(monostate, monostate) noexcept; + constexpr bool operator!=(monostate, monostate) noexcept; + + // 20.7.9, specialized algorithms + template + void swap(variant&, variant&) noexcept(see below); + + // 20.7.10, class bad_variant_access + class bad_variant_access; + + // 20.7.11, hash support + template struct hash; + template struct hash>; + template <> struct hash; + +} // namespace std + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opentelemetry/version.h" + +#include "config.hpp" +#include "in_place.hpp" +#include "lib.hpp" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ + +#ifdef MPARK_RETURN_TYPE_DEDUCTION + +#define AUTO auto +#define AUTO_RETURN(...) { return __VA_ARGS__; } + +#define AUTO_REFREF auto && +#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } + +#define DECLTYPE_AUTO decltype(auto) +#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } + +#else + +#define AUTO auto +#define AUTO_RETURN(...) \ + -> lib::decay_t { return __VA_ARGS__; } + +#define AUTO_REFREF auto +#define AUTO_REFREF_RETURN(...) \ + -> decltype((__VA_ARGS__)) { \ + static_assert(std::is_reference::value, ""); \ + return __VA_ARGS__; \ + } + +#define DECLTYPE_AUTO auto +#define DECLTYPE_AUTO_RETURN(...) \ + -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + +#endif + + class bad_variant_access : public std::exception { + public: + virtual const char *what() const noexcept override { return "bad_variant_access"; } + }; + + [[noreturn]] inline void throw_bad_variant_access() { +#ifdef MPARK_EXCEPTIONS + throw bad_variant_access{}; +#else + std::terminate(); + MPARK_BUILTIN_UNREACHABLE; +#endif + } + + template + class variant; + + template + struct variant_size; + + template + struct variant_size : variant_size {}; + + template + struct variant_size : variant_size {}; + + template + struct variant_size : variant_size {}; + + template + struct variant_size> : lib::size_constant {}; + + template + struct variant_alternative; + + template + using variant_alternative_t = typename variant_alternative::type; + + template + struct variant_alternative + : std::add_const> {}; + + template + struct variant_alternative + : std::add_volatile> {}; + + template + struct variant_alternative + : std::add_cv> {}; + + template + struct variant_alternative> { + static_assert(I < sizeof...(Ts), + "index out of bounds in `std::variant_alternative<>`"); + using type = lib::type_pack_element_t; + }; + + constexpr std::size_t variant_npos = static_cast(-1); + + namespace detail { + + constexpr std::size_t not_found = static_cast(-1); + constexpr std::size_t ambiguous = static_cast(-2); + + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t) { + return result; + } + + template + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t idx, + bool b, + Bs... bs) { + return b ? (result != not_found ? ambiguous + : find_index_impl(idx, idx + 1, bs...)) + : find_index_impl(result, idx + 1, bs...); + } + + template + inline constexpr std::size_t find_index() { + return find_index_impl(not_found, 0, std::is_same::value...); + } + + template + using find_index_sfinae_impl = + lib::enable_if_t>; + + template + using find_index_sfinae = find_index_sfinae_impl()>; + + template + struct find_index_checked_impl : lib::size_constant { + static_assert(I != not_found, "the specified type is not found."); + static_assert(I != ambiguous, "the specified type is ambiguous."); + }; + + template + using find_index_checked = find_index_checked_impl()>; + + struct valueless_t {}; + + enum class Trait { TriviallyAvailable, Available, Unavailable }; + + template class IsTriviallyAvailable, + template class IsAvailable> + inline constexpr Trait trait() { + return IsTriviallyAvailable::value + ? Trait::TriviallyAvailable + : IsAvailable::value ? Trait::Available + : Trait::Unavailable; + } + + inline constexpr Trait common_trait_impl(Trait result) { return result; } + + template + inline constexpr Trait common_trait_impl(Trait result, + Trait t, + Traits... ts) { + return static_cast(t) > static_cast(result) + ? common_trait_impl(t, ts...) + : common_trait_impl(result, ts...); + } + + template + inline constexpr Trait common_trait(Traits... ts) { + return common_trait_impl(Trait::TriviallyAvailable, ts...); + } + + template + struct traits { + static constexpr Trait copy_constructible_trait = + common_trait(trait()...); + + static constexpr Trait move_constructible_trait = + common_trait(trait()...); + + static constexpr Trait copy_assignable_trait = + common_trait(copy_constructible_trait, + trait()...); + + static constexpr Trait move_assignable_trait = + common_trait(move_constructible_trait, + trait()...); + + static constexpr Trait destructible_trait = + common_trait(trait()...); + }; + + namespace access { + + struct recursive_union { + template + struct get_alt_impl { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) + }; + + template + struct get_alt_impl<0, Dummy> { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(lib::forward(v).head_) + }; + + template + inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) + AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) + }; + + struct base { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) +#ifdef _MSC_VER + AUTO_REFREF_RETURN(recursive_union::get_alt( + lib::forward(v).data_, in_place_index_t{})) +#else + AUTO_REFREF_RETURN(recursive_union::get_alt( + data(lib::forward(v)), in_place_index_t{})) +#endif + }; + + struct variant { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) + AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) + }; + + } // namespace access + + namespace visitation { + +#if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER) +#define MPARK_VARIANT_SWITCH_VISIT +#endif + + struct base { + template + using dispatch_result_t = decltype( + lib::invoke(std::declval(), + access::base::get_alt<0>(std::declval())...)); + + template + struct expected { + template + inline static constexpr bool but_got() { + return std::is_same::value; + } + }; + + template + struct visit_return_type_check { + static_assert( + expected::template but_got(), + "`visit` requires the visitor to have a single return type"); + + template + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, + Alts &&... alts) + DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), + lib::forward(alts)...)) + }; + +#ifdef MPARK_VARIANT_SWITCH_VISIT + template + struct dispatcher; + + template + struct dispatcher { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&, typename ITs::type &&..., Vs &&...) { + MPARK_BUILTIN_UNREACHABLE; + } + + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) { + MPARK_BUILTIN_UNREACHABLE; + } + + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t, + F &&, + Vs &&...) { + MPARK_BUILTIN_UNREACHABLE; + } + }; + + template + struct dispatcher { + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&f, typename ITs::type &&... visited_vs) { + using Expected = R; + using Actual = decltype(lib::invoke( + lib::forward(f), + access::base::get_alt( + lib::forward(visited_vs))...)); + return visit_return_type_check::invoke( + lib::forward(f), + access::base::get_alt( + lib::forward(visited_vs))...); + } + + template + MPARK_ALWAYS_INLINE static constexpr R dispatch( + F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) { +#define MPARK_DISPATCH(I) \ + dispatcher<(I < lib::decay_t::size()), \ + R, \ + ITs..., \ + lib::indexed_type>:: \ + template dispatch<0>(lib::forward(f), \ + lib::forward(visited_vs)..., \ + lib::forward(v), \ + lib::forward(vs)...) + +#define MPARK_DEFAULT(I) \ + dispatcher<(I < lib::decay_t::size()), R, ITs...>::template dispatch( \ + lib::forward(f), \ + lib::forward(visited_vs)..., \ + lib::forward(v), \ + lib::forward(vs)...) + + switch (v.index()) { + case B + 0: return MPARK_DISPATCH(B + 0); + case B + 1: return MPARK_DISPATCH(B + 1); + case B + 2: return MPARK_DISPATCH(B + 2); + case B + 3: return MPARK_DISPATCH(B + 3); + case B + 4: return MPARK_DISPATCH(B + 4); + case B + 5: return MPARK_DISPATCH(B + 5); + case B + 6: return MPARK_DISPATCH(B + 6); + case B + 7: return MPARK_DISPATCH(B + 7); + case B + 8: return MPARK_DISPATCH(B + 8); + case B + 9: return MPARK_DISPATCH(B + 9); + case B + 10: return MPARK_DISPATCH(B + 10); + case B + 11: return MPARK_DISPATCH(B + 11); + case B + 12: return MPARK_DISPATCH(B + 12); + case B + 13: return MPARK_DISPATCH(B + 13); + case B + 14: return MPARK_DISPATCH(B + 14); + case B + 15: return MPARK_DISPATCH(B + 15); + case B + 16: return MPARK_DISPATCH(B + 16); + case B + 17: return MPARK_DISPATCH(B + 17); + case B + 18: return MPARK_DISPATCH(B + 18); + case B + 19: return MPARK_DISPATCH(B + 19); + case B + 20: return MPARK_DISPATCH(B + 20); + case B + 21: return MPARK_DISPATCH(B + 21); + case B + 22: return MPARK_DISPATCH(B + 22); + case B + 23: return MPARK_DISPATCH(B + 23); + case B + 24: return MPARK_DISPATCH(B + 24); + case B + 25: return MPARK_DISPATCH(B + 25); + case B + 26: return MPARK_DISPATCH(B + 26); + case B + 27: return MPARK_DISPATCH(B + 27); + case B + 28: return MPARK_DISPATCH(B + 28); + case B + 29: return MPARK_DISPATCH(B + 29); + case B + 30: return MPARK_DISPATCH(B + 30); + case B + 31: return MPARK_DISPATCH(B + 31); + default: return MPARK_DEFAULT(B + 32); + } + +#undef MPARK_DEFAULT +#undef MPARK_DISPATCH + } + + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f, + Vs &&... vs) { + using Expected = R; + using Actual = decltype( + lib::invoke(lib::forward(f), + access::base::get_alt(lib::forward(vs))...)); + return visit_return_type_check::invoke( + lib::forward(f), + access::base::get_alt(lib::forward(vs))...); + } + + template + MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index, + F &&f, + V &&v, + Vs &&... vs) { + static_assert(lib::all<(lib::decay_t::size() == + lib::decay_t::size())...>::value, + "all of the variants must be the same size."); +#define MPARK_DISPATCH_AT(I) \ + dispatcher<(I < lib::decay_t::size()), R>::template dispatch_case( \ + lib::forward(f), lib::forward(v), lib::forward(vs)...) + +#define MPARK_DEFAULT(I) \ + dispatcher<(I < lib::decay_t::size()), R>::template dispatch_at( \ + index, lib::forward(f), lib::forward(v), lib::forward(vs)...) + + switch (index) { + case B + 0: return MPARK_DISPATCH_AT(B + 0); + case B + 1: return MPARK_DISPATCH_AT(B + 1); + case B + 2: return MPARK_DISPATCH_AT(B + 2); + case B + 3: return MPARK_DISPATCH_AT(B + 3); + case B + 4: return MPARK_DISPATCH_AT(B + 4); + case B + 5: return MPARK_DISPATCH_AT(B + 5); + case B + 6: return MPARK_DISPATCH_AT(B + 6); + case B + 7: return MPARK_DISPATCH_AT(B + 7); + case B + 8: return MPARK_DISPATCH_AT(B + 8); + case B + 9: return MPARK_DISPATCH_AT(B + 9); + case B + 10: return MPARK_DISPATCH_AT(B + 10); + case B + 11: return MPARK_DISPATCH_AT(B + 11); + case B + 12: return MPARK_DISPATCH_AT(B + 12); + case B + 13: return MPARK_DISPATCH_AT(B + 13); + case B + 14: return MPARK_DISPATCH_AT(B + 14); + case B + 15: return MPARK_DISPATCH_AT(B + 15); + case B + 16: return MPARK_DISPATCH_AT(B + 16); + case B + 17: return MPARK_DISPATCH_AT(B + 17); + case B + 18: return MPARK_DISPATCH_AT(B + 18); + case B + 19: return MPARK_DISPATCH_AT(B + 19); + case B + 20: return MPARK_DISPATCH_AT(B + 20); + case B + 21: return MPARK_DISPATCH_AT(B + 21); + case B + 22: return MPARK_DISPATCH_AT(B + 22); + case B + 23: return MPARK_DISPATCH_AT(B + 23); + case B + 24: return MPARK_DISPATCH_AT(B + 24); + case B + 25: return MPARK_DISPATCH_AT(B + 25); + case B + 26: return MPARK_DISPATCH_AT(B + 26); + case B + 27: return MPARK_DISPATCH_AT(B + 27); + case B + 28: return MPARK_DISPATCH_AT(B + 28); + case B + 29: return MPARK_DISPATCH_AT(B + 29); + case B + 30: return MPARK_DISPATCH_AT(B + 30); + case B + 31: return MPARK_DISPATCH_AT(B + 31); + default: return MPARK_DEFAULT(B + 32); + } + +#undef MPARK_DEFAULT +#undef MPARK_DISPATCH_AT + } + }; +#else + template + inline static constexpr const T &at(const T &elem) noexcept { + return elem; + } + + template + inline static constexpr const lib::remove_all_extents_t &at( + const lib::array &elems, std::size_t i, Is... is) noexcept { + return at(elems[i], is...); + } + + template + inline static constexpr lib::array, sizeof...(Fs) + 1> + make_farray(F &&f, Fs &&... fs) { + return {{lib::forward(f), lib::forward(fs)...}}; + } + + template + struct make_fmatrix_impl { + + template + inline static constexpr dispatch_result_t dispatch( + F &&f, Vs &&... vs) { + using Expected = dispatch_result_t; + using Actual = decltype(lib::invoke( + lib::forward(f), + access::base::get_alt(lib::forward(vs))...)); + return visit_return_type_check::invoke( + lib::forward(f), + access::base::get_alt(lib::forward(vs))...); + } + + template + struct impl; + + template + struct impl> { + inline constexpr AUTO operator()() const + AUTO_RETURN(&dispatch) + }; + + template + struct impl, Ls...> { + inline constexpr AUTO operator()() const + AUTO_RETURN( + make_farray(impl, Ls...>{}()...)) + }; + }; + + template + inline static constexpr AUTO make_fmatrix() + AUTO_RETURN( + typename make_fmatrix_impl::template impl< + lib::index_sequence<>, + lib::make_index_sequence::size()>...>{}()) + + template + struct make_fdiagonal_impl { + template + inline static constexpr dispatch_result_t dispatch( + F &&f, Vs &&... vs) { + using Expected = dispatch_result_t; + using Actual = decltype( + lib::invoke(lib::forward(f), + access::base::get_alt(lib::forward(vs))...)); + return visit_return_type_check::invoke( + lib::forward(f), + access::base::get_alt(lib::forward(vs))...); + } + + template + inline static constexpr AUTO impl(lib::index_sequence) + AUTO_RETURN(make_farray(&dispatch...)) + }; + + template + inline static constexpr auto make_fdiagonal() + -> decltype(make_fdiagonal_impl::impl( + lib::make_index_sequence::size()>{})) { + static_assert(lib::all<(lib::decay_t::size() == + lib::decay_t::size())...>::value, + "all of the variants must be the same size."); + return make_fdiagonal_impl::impl( + lib::make_index_sequence::size()>{}); + } +#endif + }; + +#if !defined(MPARK_VARIANT_SWITCH_VISIT) && \ + (!defined(_MSC_VER) || _MSC_VER >= 1910) + template + using fmatrix_t = decltype(base::make_fmatrix()); + + template + struct fmatrix { + static constexpr fmatrix_t value = + base::make_fmatrix(); + }; + + template + constexpr fmatrix_t fmatrix::value; + + template + using fdiagonal_t = decltype(base::make_fdiagonal()); + + template + struct fdiagonal { + static constexpr fdiagonal_t value = + base::make_fdiagonal(); + }; + + template + constexpr fdiagonal_t fdiagonal::value; +#endif + + struct alt { + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) +#ifdef MPARK_VARIANT_SWITCH_VISIT + DECLTYPE_AUTO_RETURN( + base::dispatcher< + true, + base::dispatch_result_t(vs)))...>>:: + template dispatch<0>(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#elif !defined(_MSC_VER) || _MSC_VER >= 1910 + DECLTYPE_AUTO_RETURN(base::at( + fmatrix(vs)))...>::value, + vs.index()...)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#else + DECLTYPE_AUTO_RETURN(base::at( + base::make_fmatrix(vs)))...>(), + vs.index()...)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#endif + + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) +#ifdef MPARK_VARIANT_SWITCH_VISIT + DECLTYPE_AUTO_RETURN( + base::dispatcher< + true, + base::dispatch_result_t(vs)))...>>:: + template dispatch_at<0>(index, + lib::forward(visitor), + as_base(lib::forward(vs))...)) +#elif !defined(_MSC_VER) || _MSC_VER >= 1910 + DECLTYPE_AUTO_RETURN(base::at( + fdiagonal(vs)))...>::value, + index)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#else + DECLTYPE_AUTO_RETURN(base::at( + base::make_fdiagonal(vs)))...>(), + index)(lib::forward(visitor), + as_base(lib::forward(vs))...)) +#endif + }; + + struct variant { + private: + template + struct visitor { + template + inline static constexpr bool does_not_handle() { + return lib::is_invocable::value; + } + }; + + template + struct visit_exhaustiveness_check { + static_assert(visitor::template does_not_handle(), + "`visit` requires the visitor to be exhaustive."); + + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, + Values &&... values) + DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), + lib::forward(values)...)) + }; + + template + struct value_visitor { + Visitor &&visitor_; + + template + inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const + DECLTYPE_AUTO_RETURN( + visit_exhaustiveness_check< + Visitor, + decltype((lib::forward(alts).value))...>:: + invoke(lib::forward(visitor_), + lib::forward(alts).value...)) + }; + + template + inline static constexpr AUTO make_value_visitor(Visitor &&visitor) + AUTO_RETURN(value_visitor{lib::forward(visitor)}) + + public: + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), + lib::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + alt::visit_alt_at(index, + lib::forward(visitor), + lib::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt(make_value_visitor(lib::forward(visitor)), + lib::forward(vs)...)) + + template + inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt_at(index, + make_value_visitor(lib::forward(visitor)), + lib::forward(vs)...)) + }; + + } // namespace visitation + + template + struct alt { + using value_type = T; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + template + inline explicit constexpr alt(in_place_t, Args &&... args) + : value(lib::forward(args)...) {} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + T value; + }; + + template + union recursive_union; + + template + union recursive_union {}; + +#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ + template \ + union recursive_union { \ + public: \ + inline explicit constexpr recursive_union(valueless_t) noexcept \ + : dummy_{} {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t<0>, \ + Args &&... args) \ + : head_(in_place_t{}, lib::forward(args)...) {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t, \ + Args &&... args) \ + : tail_(in_place_index_t{}, lib::forward(args)...) {} \ + \ + recursive_union(const recursive_union &) = default; \ + recursive_union(recursive_union &&) = default; \ + \ + destructor \ + \ + recursive_union &operator=(const recursive_union &) = default; \ + recursive_union &operator=(recursive_union &&) = default; \ + \ + private: \ + char dummy_; \ + alt head_; \ + recursive_union tail_; \ + \ + friend struct access::recursive_union; \ + } + + MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, + ~recursive_union() = default;); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, + ~recursive_union() {}); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, + ~recursive_union() = delete;); + +#undef MPARK_VARIANT_RECURSIVE_UNION + + template + using index_t = typename std::conditional< + sizeof...(Ts) < (std::numeric_limits::max)(), + unsigned char, + typename std::conditional< + sizeof...(Ts) < (std::numeric_limits::max)(), + unsigned short, + unsigned int>::type + >::type; + + template + class base { + public: + inline explicit constexpr base(valueless_t tag) noexcept + : data_(tag), index_(static_cast>(-1)) {} + + template + inline explicit constexpr base(in_place_index_t, Args &&... args) + : data_(in_place_index_t{}, lib::forward(args)...), + index_(I) {} + + inline constexpr bool valueless_by_exception() const noexcept { + return index_ == static_cast>(-1); + } + + inline constexpr std::size_t index() const noexcept { + return valueless_by_exception() ? variant_npos : index_; + } + + protected: + using data_t = recursive_union; + + friend inline constexpr base &as_base(base &b) { return b; } + friend inline constexpr const base &as_base(const base &b) { return b; } + friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } + friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } + + friend inline constexpr data_t &data(base &b) { return b.data_; } + friend inline constexpr const data_t &data(const base &b) { return b.data_; } + friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } + friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } + + inline static constexpr std::size_t size() { return sizeof...(Ts); } + + data_t data_; + index_t index_; + + friend struct access::base; + friend struct visitation::base; + }; + + struct dtor { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template + inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + +#if !defined(_MSC_VER) || _MSC_VER >= 1910 +#define MPARK_INHERITING_CTOR(type, base) using base::base; +#else +#define MPARK_INHERITING_CTOR(type, base) \ + template \ + inline explicit constexpr type(Args &&... args) \ + : base(lib::forward(args)...) {} +#endif + + template + class destructor; + +#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ + template \ + class destructor, destructible_trait> \ + : public base { \ + using super = base; \ + \ + public: \ + MPARK_INHERITING_CTOR(destructor, super) \ + using super::operator=; \ + \ + destructor(const destructor &) = default; \ + destructor(destructor &&) = default; \ + definition \ + destructor &operator=(const destructor &) = default; \ + destructor &operator=(destructor &&) = default; \ + \ + protected: \ + destroy \ + } + + MPARK_VARIANT_DESTRUCTOR( + Trait::TriviallyAvailable, + ~destructor() = default;, + inline void destroy() noexcept { + this->index_ = static_cast>(-1); + }); + + MPARK_VARIANT_DESTRUCTOR( + Trait::Available, + ~destructor() { destroy(); }, + inline void destroy() noexcept { + if (!this->valueless_by_exception()) { + visitation::alt::visit_alt(dtor{}, *this); + } + this->index_ = static_cast>(-1); + }); + + MPARK_VARIANT_DESTRUCTOR( + Trait::Unavailable, + ~destructor() = delete;, + inline void destroy() noexcept = delete;); + +#undef MPARK_VARIANT_DESTRUCTOR + + template + class constructor : public destructor { + using super = destructor; + + public: + MPARK_INHERITING_CTOR(constructor, super) + using super::operator=; + + protected: +#ifndef MPARK_GENERIC_LAMBDAS + struct ctor { + template + inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { + constructor::construct_alt(lhs_alt, + lib::forward(rhs_alt).value); + } + }; +#endif + + template + inline static T &construct_alt(alt &a, Args &&... args) { + auto *result = ::new (static_cast(lib::addressof(a))) + alt(in_place_t{}, lib::forward(args)...); + return result->value; + } + + template + inline static void generic_construct(constructor &lhs, Rhs &&rhs) { + lhs.destroy(); + if (!rhs.valueless_by_exception()) { + visitation::alt::visit_alt_at( + rhs.index(), +#ifdef MPARK_GENERIC_LAMBDAS + [](auto &lhs_alt, auto &&rhs_alt) { + constructor::construct_alt( + lhs_alt, lib::forward(rhs_alt).value); + } +#else + ctor{} +#endif + , + lhs, + lib::forward(rhs)); + lhs.index_ = rhs.index_; + } + } + }; + + template + class move_constructor; + +#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ + template \ + class move_constructor, move_constructible_trait> \ + : public constructor> { \ + using super = constructor>; \ + \ + public: \ + MPARK_INHERITING_CTOR(move_constructor, super) \ + using super::operator=; \ + \ + move_constructor(const move_constructor &) = default; \ + definition \ + ~move_constructor() = default; \ + move_constructor &operator=(const move_constructor &) = default; \ + move_constructor &operator=(move_constructor &&) = default; \ + } + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::TriviallyAvailable, + move_constructor(move_constructor &&that) = default;); + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Available, + move_constructor(move_constructor &&that) noexcept( + lib::all::value...>::value) + : move_constructor(valueless_t{}) { + this->generic_construct(*this, lib::move(that)); + }); + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Unavailable, + move_constructor(move_constructor &&) = delete;); + +#undef MPARK_VARIANT_MOVE_CONSTRUCTOR + + template + class copy_constructor; + +#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ + template \ + class copy_constructor, copy_constructible_trait> \ + : public move_constructor> { \ + using super = move_constructor>; \ + \ + public: \ + MPARK_INHERITING_CTOR(copy_constructor, super) \ + using super::operator=; \ + \ + definition \ + copy_constructor(copy_constructor &&) = default; \ + ~copy_constructor() = default; \ + copy_constructor &operator=(const copy_constructor &) = default; \ + copy_constructor &operator=(copy_constructor &&) = default; \ + } + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::TriviallyAvailable, + copy_constructor(const copy_constructor &that) = default;); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Available, + copy_constructor(const copy_constructor &that) + : copy_constructor(valueless_t{}) { + this->generic_construct(*this, that); + }); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Unavailable, + copy_constructor(const copy_constructor &) = delete;); + +#undef MPARK_VARIANT_COPY_CONSTRUCTOR + + template + class assignment : public copy_constructor { + using super = copy_constructor; + + public: + MPARK_INHERITING_CTOR(assignment, super) + using super::operator=; + + template + inline /* auto & */ auto emplace(Args &&... args) + -> decltype(this->construct_alt(access::base::get_alt(*this), + lib::forward(args)...)) { + this->destroy(); + auto &result = this->construct_alt(access::base::get_alt(*this), + lib::forward(args)...); + this->index_ = I; + return result; + } + + protected: + template + struct assigner { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { + self->assign_alt(this_alt, lib::forward(that_alt).value); + } + assignment *self; + }; + + template + inline void assign_alt(alt &a, Arg &&arg) { + if (this->index() == I) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + a.value = lib::forward(arg); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } else { + struct { + void operator()(std::true_type) const { + this_->emplace(lib::forward(arg_)); + } + void operator()(std::false_type) const { + this_->emplace(T(lib::forward(arg_))); + } + assignment *this_; + Arg &&arg_; + } impl{this, lib::forward(arg)}; + impl(lib::bool_constant< + std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value>{}); + } + } + + template + inline void generic_assign(That &&that) { + if (this->valueless_by_exception() && that.valueless_by_exception()) { + // do nothing. + } else if (that.valueless_by_exception()) { + this->destroy(); + } else { + visitation::alt::visit_alt_at( + that.index(), + assigner{this} + , + *this, + lib::forward(that)); + } + } + }; + + template + class move_assignment; + +#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ + template \ + class move_assignment, move_assignable_trait> \ + : public assignment> { \ + using super = assignment>; \ + \ + public: \ + MPARK_INHERITING_CTOR(move_assignment, super) \ + using super::operator=; \ + \ + move_assignment(const move_assignment &) = default; \ + move_assignment(move_assignment &&) = default; \ + ~move_assignment() = default; \ + move_assignment &operator=(const move_assignment &) = default; \ + definition \ + } + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::TriviallyAvailable, + move_assignment &operator=(move_assignment &&that) = default;); + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Available, + move_assignment & + operator=(move_assignment &&that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value)...>::value) { + this->generic_assign(lib::move(that)); + return *this; + }); + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Unavailable, + move_assignment &operator=(move_assignment &&) = delete;); + +#undef MPARK_VARIANT_MOVE_ASSIGNMENT + + template + class copy_assignment; + +#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ + template \ + class copy_assignment, copy_assignable_trait> \ + : public move_assignment> { \ + using super = move_assignment>; \ + \ + public: \ + MPARK_INHERITING_CTOR(copy_assignment, super) \ + using super::operator=; \ + \ + copy_assignment(const copy_assignment &) = default; \ + copy_assignment(copy_assignment &&) = default; \ + ~copy_assignment() = default; \ + definition \ + copy_assignment &operator=(copy_assignment &&) = default; \ + } + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::TriviallyAvailable, + copy_assignment &operator=(const copy_assignment &that) = default;); + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Available, + copy_assignment &operator=(const copy_assignment &that) { + this->generic_assign(that); + return *this; + }); + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Unavailable, + copy_assignment &operator=(const copy_assignment &) = delete;); + +#undef MPARK_VARIANT_COPY_ASSIGNMENT + + template + class impl : public copy_assignment> { + using super = copy_assignment>; + + public: + MPARK_INHERITING_CTOR(impl, super) + using super::operator=; + + impl(const impl&) = default; + impl(impl&&) = default; + ~impl() = default; + impl &operator=(const impl &) = default; + impl &operator=(impl &&) = default; + + template + inline void assign(Arg &&arg) { + this->assign_alt(access::base::get_alt(*this), + lib::forward(arg)); + } + + inline void swap(impl &that) { + if (this->valueless_by_exception() && that.valueless_by_exception()) { + // do nothing. + } else if (this->index() == that.index()) { + visitation::alt::visit_alt_at(this->index(), + swapper{} + , + *this, + that); + } else { + impl *lhs = this; + impl *rhs = lib::addressof(that); + if (lhs->move_nothrow() && !rhs->move_nothrow()) { + std::swap(lhs, rhs); + } + impl tmp(lib::move(*rhs)); +#ifdef MPARK_EXCEPTIONS + // EXTENSION: When the move construction of `lhs` into `rhs` throws + // and `tmp` is nothrow move constructible then we move `tmp` back + // into `rhs` and provide the strong exception safety guarantee. + try { + this->generic_construct(*rhs, lib::move(*lhs)); + } catch (...) { + if (tmp.move_nothrow()) { + this->generic_construct(*rhs, lib::move(tmp)); + } + throw; + } +#else + this->generic_construct(*rhs, lib::move(*lhs)); +#endif + this->generic_construct(*lhs, lib::move(tmp)); + } + } + + private: + struct swapper { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { + using std::swap; + swap(this_alt.value, that_alt.value); + } + }; + + inline constexpr bool move_nothrow() const { + return this->valueless_by_exception() || + lib::array{ + {std::is_nothrow_move_constructible::value...} + }[this->index()]; + } + }; + +#undef MPARK_INHERITING_CTOR + + template + struct is_non_narrowing_convertible { + template + static std::true_type test(T(&&)[1]); + + template + static auto impl(int) -> decltype(test({std::declval()})); + + template + static auto impl(...) -> std::false_type; + + static constexpr bool value = decltype(impl(0))::value; + }; + + template ::value, + typename = void> + struct overload_leaf {}; + + template + struct overload_leaf { + using impl = lib::size_constant (*)(T); + operator impl() const { return nullptr; }; + }; + + template + struct overload_leaf< + Arg, + I, + T, + true +#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5 + , + lib::enable_if_t< + std::is_same, bool>::value + ? std::is_same, bool>::value + : is_non_narrowing_convertible::value> +#endif + > { + using impl = lib::size_constant (*)(T); + operator impl() const { return nullptr; }; + }; + + template + struct overload_impl { + private: + template + struct impl; + + template + struct impl> : overload_leaf... {}; + + public: + using type = impl>; + }; + + template + using overload = typename overload_impl::type; + + template + using best_match = lib::invoke_result_t, Arg>; + + template + struct is_in_place_index : std::false_type {}; + + template + struct is_in_place_index> : std::true_type {}; + + template + struct is_in_place_type : std::false_type {}; + + template + struct is_in_place_type> : std::true_type {}; + + } // detail + + template + class variant { + static_assert(0 < sizeof...(Ts), + "variant must consist of at least one alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have an array type as an alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have a reference type as an alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have a void type as an alternative."); + + public: + template < + typename Front = lib::type_pack_element_t<0, Ts...>, + lib::enable_if_t::value, int> = 0> + inline constexpr variant() noexcept( + std::is_nothrow_default_constructible::value) + : impl_(in_place_index_t<0>{}) {} + + variant(const variant &) = default; + variant(variant &&) = default; + + template < + typename Arg, + typename Decayed = lib::decay_t, + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline constexpr variant(Arg &&arg) noexcept( + std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(arg)) {} + + template < + std::size_t I, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline explicit constexpr variant( + in_place_index_t, + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline explicit constexpr variant( + in_place_index_t, + std::initializer_list il, + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} + + template < + typename T, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t::value, int> = 0> + inline explicit constexpr variant( + in_place_type_t, + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} + + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline explicit constexpr variant( + in_place_type_t, + std::initializer_list il, + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} + + ~variant() = default; + + variant &operator=(const variant &) = default; + variant &operator=(variant &&) = default; + + template , variant>::value, + int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, + lib::enable_if_t<(std::is_assignable::value && + std::is_constructible::value), + int> = 0> + inline variant &operator=(Arg &&arg) noexcept( + (std::is_nothrow_assignable::value && + std::is_nothrow_constructible::value)) { + impl_.template assign(lib::forward(arg)); + return *this; + } + + template < + std::size_t I, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); + } + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); + } + + template < + typename T, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); + } + + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); + } + + inline constexpr bool valueless_by_exception() const noexcept { + return impl_.valueless_by_exception(); + } + + inline constexpr std::size_t index() const noexcept { + return impl_.index(); + } + + template , + Dummy>::value && + lib::dependent_type, + Dummy>::value)...>::value, + int> = 0> + inline void swap(variant &that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + lib::is_nothrow_swappable::value)...>::value) { + impl_.swap(that.impl_); + } + + private: + detail::impl impl_; + + friend struct detail::access::variant; + friend struct detail::visitation::variant; + }; + + template + inline constexpr bool holds_alternative(const variant &v) noexcept { + return v.index() == I; + } + + template + inline constexpr bool holds_alternative(const variant &v) noexcept { + return holds_alternative::value>(v); + } + + namespace detail { + template + struct generic_get_impl { + constexpr generic_get_impl(int) noexcept {} + + constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN( + access::variant::get_alt(lib::forward(v)).value) + }; + + template + inline constexpr AUTO_REFREF generic_get(V &&v) + AUTO_REFREF_RETURN(generic_get_impl( + holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))( + lib::forward(v))) + } // namespace detail + + template + inline constexpr variant_alternative_t> &get( + variant &v) { + return detail::generic_get(v); + } + + template + inline constexpr variant_alternative_t> &&get( + variant &&v) { + return detail::generic_get(lib::move(v)); + } + + template + inline constexpr const variant_alternative_t> &get( + const variant &v) { + return detail::generic_get(v); + } + + template + inline constexpr const variant_alternative_t> &&get( + const variant &&v) { + return detail::generic_get(lib::move(v)); + } + + template + inline constexpr T &get(variant &v) { + return get::value>(v); + } + + template + inline constexpr T &&get(variant &&v) { + return get::value>(lib::move(v)); + } + + template + inline constexpr const T &get(const variant &v) { + return get::value>(v); + } + + template + inline constexpr const T &&get(const variant &&v) { + return get::value>(lib::move(v)); + } + + namespace detail { + + template + inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept + AUTO_RETURN(v && holds_alternative(*v) + ? lib::addressof(access::variant::get_alt(*v).value) + : nullptr) + + } // namespace detail + + template + inline constexpr lib::add_pointer_t>> + get_if(variant *v) noexcept { + return detail::generic_get_if(v); + } + + template + inline constexpr lib::add_pointer_t< + const variant_alternative_t>> + get_if(const variant *v) noexcept { + return detail::generic_get_if(v); + } + + template + inline constexpr lib::add_pointer_t + get_if(variant *v) noexcept { + return get_if::value>(v); + } + + template + inline constexpr lib::add_pointer_t + get_if(const variant *v) noexcept { + return get_if::value>(v); + } + + namespace detail { + template + struct convert_to_bool { + template + inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const { + static_assert(std::is_convertible, + bool>::value, + "relational operators must return a type" + " implicitly convertible to bool"); + return lib::invoke( + RelOp{}, lib::forward(lhs), lib::forward(rhs)); + } + }; + } // namespace detail + + template + inline constexpr bool operator==(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using equal_to = detail::convert_to_bool; + return lhs.index() == rhs.index() && + (lhs.valueless_by_exception() || + variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); + } + + template + inline constexpr bool operator!=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using not_equal_to = detail::convert_to_bool; + return lhs.index() != rhs.index() || + (!lhs.valueless_by_exception() && + variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); + } + + template + inline constexpr bool operator<(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using less = detail::convert_to_bool; + return !rhs.valueless_by_exception() && + (lhs.valueless_by_exception() || lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); + } + + template + inline constexpr bool operator>(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using greater = detail::convert_to_bool; + return !lhs.valueless_by_exception() && + (rhs.valueless_by_exception() || lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); + } + + template + inline constexpr bool operator<=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using less_equal = detail::convert_to_bool; + return lhs.valueless_by_exception() || + (!rhs.valueless_by_exception() && + (lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); + } + + template + inline constexpr bool operator>=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using greater_equal = detail::convert_to_bool; + return rhs.valueless_by_exception() || + (!lhs.valueless_by_exception() && + (lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at( + lhs.index(), greater_equal{}, lhs, rhs)))); + } + + struct monostate {}; + + inline constexpr bool operator<(monostate, monostate) noexcept { + return false; + } + + inline constexpr bool operator>(monostate, monostate) noexcept { + return false; + } + + inline constexpr bool operator<=(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator>=(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator==(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator!=(monostate, monostate) noexcept { + return false; + } + + namespace detail { + + template + inline constexpr bool all_impl(const lib::array &bs, + std::size_t idx) { + return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); + } + + template + inline constexpr bool all(const lib::array &bs) { + return all_impl(bs, 0); + } + + } // namespace detail + + template + inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN( + (detail::all( + lib::array{{!vs.valueless_by_exception()...}}) + ? (void)0 + : throw_bad_variant_access()), + detail::visitation::variant::visit_value(lib::forward(visitor), + lib::forward(vs)...)) + template + inline auto swap(variant &lhs, + variant &rhs) noexcept(noexcept(lhs.swap(rhs))) + -> decltype(lhs.swap(rhs)) { + lhs.swap(rhs); + } + + namespace detail { + + template + using enabled_type = T; + + namespace hash { + + template + constexpr bool meets_requirements() noexcept { + return std::is_copy_constructible::value && + std::is_move_constructible::value && + lib::is_invocable_r::value; + } + + template + constexpr bool is_enabled() noexcept { + using H = std::hash; + return meets_requirements() && + std::is_default_constructible::value && + std::is_copy_assignable::value && + std::is_move_assignable::value; + } + + } // namespace hash + + } // namespace detail + +#undef AUTO +#undef AUTO_RETURN + +#undef AUTO_REFREF +#undef AUTO_REFREF_RETURN + +#undef DECLTYPE_AUTO +#undef DECLTYPE_AUTO_RETURN + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + +namespace std { + + template + struct hash, + mpark::lib::enable_if_t>()...>::value>>> { + using argument_type = mpark::variant; + using result_type = std::size_t; + + inline result_type operator()(const argument_type &v) const { + using mpark::detail::visitation::variant; + std::size_t result = + v.valueless_by_exception() + ? 299792458 // Random value chosen by the universe upon creation + : variant::visit_alt( + hasher{} + , + v); + return hash_combine(result, hash{}(v.index())); + } + + private: + struct hasher { + template + inline std::size_t operator()(const Alt &alt) const { + using alt_type = mpark::lib::decay_t; + using value_type = + mpark::lib::remove_const_t; + return hash{}(alt.value); + } + }; + + static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { + return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); + } + }; + + template <> + struct hash { + using argument_type = mpark::monostate; + using result_type = std::size_t; + + inline result_type operator()(const argument_type &) const noexcept { + return 66740831; // return a fundamentally attractive random value. + } + }; + +} // namespace std From 0f7b21777759d1f7c3026ca01bd6054ba08b8087 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 30 Mar 2020 22:25:14 -0700 Subject: [PATCH 02/42] Fill out variant backport --- .../opentelemetry/nostd/detail/type_pack.h | 40 +++++++++++++++ api/include/opentelemetry/nostd/utility.h | 49 +++++++++++++++++++ api/include/opentelemetry/nostd/variant.h | 1 + api/test/nostd/BUILD | 11 +++++ api/test/nostd/utility_test.cc | 9 ++++ api/test/nostd/variant_test.cc | 5 ++ 6 files changed, 115 insertions(+) create mode 100644 api/include/opentelemetry/nostd/detail/type_pack.h create mode 100644 api/include/opentelemetry/nostd/variant.h create mode 100644 api/test/nostd/variant_test.cc diff --git a/api/include/opentelemetry/nostd/detail/type_pack.h b/api/include/opentelemetry/nostd/detail/type_pack.h new file mode 100644 index 0000000000..48b46870d9 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/type_pack.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +template +struct type_pack_element_impl +{ +private: + template + struct set; + + template + struct set> : indexed_type... + {}; + + template + inline static std::enable_if impl(indexed_type); + + inline static std::enable_if impl(...); + +public: + using type = decltype(impl(set>{})); +}; + +template +using type_pack_element = typename type_pack_element_impl::type; + +template +using type_pack_element_t = typename type_pack_element::type; +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index b3c04ba9db..1a8bcb9e99 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -53,5 +53,54 @@ size_t size(T (&array)[N]) noexcept { return N; } + +/** + * Back port of std::integer_sequence + */ +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept { return sizeof...(Is); } +}; + +/** + * Back port of std::index_sequence + */ +template +using index_sequence = integer_sequence; + +/** + * Back port of std::make_index_sequence + */ +namespace detail { +template +struct index_sequence_push_back {}; + +template +struct index_sequence_push_back, I> { + using type = index_sequence; +}; + +template +struct make_index_sequence_impl { + using type = typename index_sequence_push_back::type, + N - 1>::type; +}; + +template <> +struct make_index_sequence_impl<0> { + using type = index_sequence<>; +}; +} // namespace detail + +template +using make_index_sequence = typename detail::make_index_sequence_impl::type; + +/** + * Back port of std::index_sequence_for + */ +template +using index_sequence_for = make_index_sequence; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/api/include/opentelemetry/nostd/variant.h @@ -0,0 +1 @@ +#pragma once diff --git a/api/test/nostd/BUILD b/api/test/nostd/BUILD index c3f2d6864f..8acfb7c709 100644 --- a/api/test/nostd/BUILD +++ b/api/test/nostd/BUILD @@ -9,6 +9,17 @@ cc_test( ], ) +cc_test( + name = "variant_test", + srcs = [ + "variant_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "unique_ptr_test", srcs = [ diff --git a/api/test/nostd/utility_test.cc b/api/test/nostd/utility_test.cc index ab477f40b8..3e924bc4c7 100644 --- a/api/test/nostd/utility_test.cc +++ b/api/test/nostd/utility_test.cc @@ -39,3 +39,12 @@ TEST(UtilityTest, Size) EXPECT_FALSE(decltype(IsSizeCallable(x)){}); } + +TEST(UtilityTest, MakeIndexSequence) { + EXPECT_TRUE((std::is_same, + opentelemetry::nostd::index_sequence<>>::value)); + EXPECT_TRUE((std::is_same, + opentelemetry::nostd::index_sequence<0>>::value)); + EXPECT_TRUE((std::is_same, + opentelemetry::nostd::index_sequence<0, 1>>::value)); +} diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc new file mode 100644 index 0000000000..9710a86ac2 --- /dev/null +++ b/api/test/nostd/variant_test.cc @@ -0,0 +1,5 @@ +#include "opentelemetry/nostd/variant.h" + +#include + +/* using opentelemetry::nostd::variant; */ From 642eb7394c6d4e15c98499ac77fff7f35d63c9c6 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Tue, 31 Mar 2020 15:09:28 -0700 Subject: [PATCH 03/42] Add type_pack_element --- .../nostd/detail/{type_pack.h => type_pack_element.h} | 10 ++++++++++ api/include/opentelemetry/nostd/variant.h | 2 ++ api/include/opentelemetry/nostd/variant.hpp | 9 --------- api/test/nostd/variant_test.cc | 9 +++++++++ 4 files changed, 21 insertions(+), 9 deletions(-) rename api/include/opentelemetry/nostd/detail/{type_pack.h => type_pack_element.h} (79%) diff --git a/api/include/opentelemetry/nostd/detail/type_pack.h b/api/include/opentelemetry/nostd/detail/type_pack_element.h similarity index 79% rename from api/include/opentelemetry/nostd/detail/type_pack.h rename to api/include/opentelemetry/nostd/detail/type_pack_element.h index 48b46870d9..0c522dd280 100644 --- a/api/include/opentelemetry/nostd/detail/type_pack.h +++ b/api/include/opentelemetry/nostd/detail/type_pack_element.h @@ -3,6 +3,7 @@ #include #include +#include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -10,6 +11,15 @@ namespace nostd { namespace detail { +template +using size_constant = std::integral_constant; + +template +struct indexed_type : size_constant +{ + using type = T; +}; + template struct type_pack_element_impl { diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 6f70f09bee..530bb41f65 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -1 +1,3 @@ #pragma once + +#include "opentelemetry/nostd/detail/type_pack_element.h" diff --git a/api/include/opentelemetry/nostd/variant.hpp b/api/include/opentelemetry/nostd/variant.hpp index 537d938813..19c51f6e6f 100644 --- a/api/include/opentelemetry/nostd/variant.hpp +++ b/api/include/opentelemetry/nostd/variant.hpp @@ -1087,7 +1087,6 @@ namespace nostd using super::operator=; protected: -#ifndef MPARK_GENERIC_LAMBDAS struct ctor { template inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { @@ -1095,7 +1094,6 @@ namespace nostd lib::forward(rhs_alt).value); } }; -#endif template inline static T &construct_alt(alt &a, Args &&... args) { @@ -1110,14 +1108,7 @@ namespace nostd if (!rhs.valueless_by_exception()) { visitation::alt::visit_alt_at( rhs.index(), -#ifdef MPARK_GENERIC_LAMBDAS - [](auto &lhs_alt, auto &&rhs_alt) { - constructor::construct_alt( - lhs_alt, lib::forward(rhs_alt).value); - } -#else ctor{} -#endif , lhs, lib::forward(rhs)); diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 9710a86ac2..d718860cbc 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -1,5 +1,14 @@ #include "opentelemetry/nostd/variant.h" +#include + #include /* using opentelemetry::nostd::variant; */ + +TEST(TypePackElementTest, IndexedType) { + using opentelemetry::nostd::detail::type_pack_element_t; + EXPECT_TRUE((std::is_same, int>::value)); + EXPECT_TRUE((std::is_same, double>::value)); + EXPECT_TRUE((std::is_same, char>::value)); +} From cdb6281948a2bff86f2f7391f9e39605050f17c2 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Tue, 31 Mar 2020 15:22:12 -0700 Subject: [PATCH 04/42] Add variant_size --- .../opentelemetry/nostd/detail/variant_fwd.h | 11 +++++++ .../opentelemetry/nostd/detail/variant_size.h | 30 +++++++++++++++++++ api/include/opentelemetry/nostd/variant.h | 1 + api/test/nostd/variant_test.cc | 9 +++++- 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 api/include/opentelemetry/nostd/detail/variant_fwd.h create mode 100644 api/include/opentelemetry/nostd/detail/variant_size.h diff --git a/api/include/opentelemetry/nostd/detail/variant_fwd.h b/api/include/opentelemetry/nostd/detail/variant_fwd.h new file mode 100644 index 0000000000..6d2d1ef9ec --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/variant_fwd.h @@ -0,0 +1,11 @@ +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template +class variant; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/variant_size.h b/api/include/opentelemetry/nostd/detail/variant_size.h new file mode 100644 index 0000000000..0814710305 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/variant_size.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/detail/variant_fwd.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template +struct variant_size; + +template +struct variant_size : variant_size +{}; + +template +struct variant_size : variant_size +{}; + +template +struct variant_size : variant_size +{}; + +template +struct variant_size> : std::integral_constant +{}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 530bb41f65..8d418288b4 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -1,3 +1,4 @@ #pragma once #include "opentelemetry/nostd/detail/type_pack_element.h" +#include "opentelemetry/nostd/detail/variant_size.h" diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index d718860cbc..567dc41af1 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -4,7 +4,8 @@ #include -/* using opentelemetry::nostd::variant; */ +using opentelemetry::nostd::variant; +using opentelemetry::nostd::variant_size; TEST(TypePackElementTest, IndexedType) { using opentelemetry::nostd::detail::type_pack_element_t; @@ -12,3 +13,9 @@ TEST(TypePackElementTest, IndexedType) { EXPECT_TRUE((std::is_same, double>::value)); EXPECT_TRUE((std::is_same, char>::value)); } + +TEST(VariantSizeTest, GetVariantSize) { + EXPECT_EQ(variant_size>::value, 0); + EXPECT_EQ(variant_size>::value, 1); + EXPECT_EQ((variant_size>::value), 2); +} From 8aee486960c3d840f4b06764e947ff33f8dfb210 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Tue, 31 Mar 2020 15:29:12 -0700 Subject: [PATCH 05/42] Add variant_alternative --- .../nostd/detail/variant_alternative.h | 37 +++++++++++++++++++ api/include/opentelemetry/nostd/variant.h | 1 + api/test/nostd/variant_test.cc | 21 ++++++++--- 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 api/include/opentelemetry/nostd/detail/variant_alternative.h diff --git a/api/include/opentelemetry/nostd/detail/variant_alternative.h b/api/include/opentelemetry/nostd/detail/variant_alternative.h new file mode 100644 index 0000000000..1bc5037acf --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/variant_alternative.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/detail/variant_fwd.h" +#include "opentelemetry/nostd/detail/type_pack_element.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template +struct variant_alternative; + +template +using variant_alternative_t = typename variant_alternative::type; + +template +struct variant_alternative : std::add_const> +{}; + +template +struct variant_alternative : std::add_volatile> +{}; + +template +struct variant_alternative : std::add_cv> +{}; + +template +struct variant_alternative> +{ + static_assert(I < sizeof...(Ts), "index out of bounds in `std::variant_alternative<>`"); + using type = detail::type_pack_element_t; +}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 8d418288b4..0862695eb5 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -2,3 +2,4 @@ #include "opentelemetry/nostd/detail/type_pack_element.h" #include "opentelemetry/nostd/detail/variant_size.h" +#include "opentelemetry/nostd/detail/variant_alternative.h" diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 567dc41af1..37f88d3cfd 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -5,17 +5,28 @@ #include using opentelemetry::nostd::variant; +using opentelemetry::nostd::variant_alternative_t; using opentelemetry::nostd::variant_size; -TEST(TypePackElementTest, IndexedType) { +TEST(TypePackElementTest, IndexedType) +{ using opentelemetry::nostd::detail::type_pack_element_t; EXPECT_TRUE((std::is_same, int>::value)); EXPECT_TRUE((std::is_same, double>::value)); EXPECT_TRUE((std::is_same, char>::value)); } -TEST(VariantSizeTest, GetVariantSize) { - EXPECT_EQ(variant_size>::value, 0); - EXPECT_EQ(variant_size>::value, 1); - EXPECT_EQ((variant_size>::value), 2); +TEST(VariantSizeTest, GetVariantSize) +{ + EXPECT_EQ(variant_size>::value, 0); + EXPECT_EQ(variant_size>::value, 1); + EXPECT_EQ((variant_size>::value), 2); +} + +TEST(VariantAlternativeTest, GetVariantSize) +{ + EXPECT_TRUE((std::is_same>, int>::value)); + EXPECT_TRUE((std::is_same>, double>::value)); + EXPECT_TRUE( + (std::is_same>, const double>::value)); } From 56332bcc42e4598afa68a93fb3914044fef377fa Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Tue, 31 Mar 2020 20:30:28 -0700 Subject: [PATCH 06/42] Fill out variant --- .../opentelemetry/nostd/detail/common_trait.h | 71 +++ .../opentelemetry/nostd/detail/decay.h | 13 + .../opentelemetry/nostd/detail/find_index.h | 52 +++ .../opentelemetry/nostd/detail/invoke.h | 103 +++++ api/include/opentelemetry/nostd/in_place.hpp | 24 +- api/include/opentelemetry/nostd/utility.h | 35 ++ api/include/opentelemetry/nostd/variant.h | 323 +++++++++++++- api/include/opentelemetry/nostd/variant.hpp | 411 ------------------ 8 files changed, 612 insertions(+), 420 deletions(-) create mode 100644 api/include/opentelemetry/nostd/detail/common_trait.h create mode 100644 api/include/opentelemetry/nostd/detail/decay.h create mode 100644 api/include/opentelemetry/nostd/detail/find_index.h create mode 100644 api/include/opentelemetry/nostd/detail/invoke.h diff --git a/api/include/opentelemetry/nostd/detail/common_trait.h b/api/include/opentelemetry/nostd/detail/common_trait.h new file mode 100644 index 0000000000..be2c3f849b --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/common_trait.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +enum class Trait +{ + TriviallyAvailable, + Available, + Unavailable +}; + +template + class IsTriviallyAvailable, + template + class IsAvailable> +inline constexpr Trait trait() +{ + return IsTriviallyAvailable::value + ? Trait::TriviallyAvailable + : IsAvailable::value ? Trait::Available : Trait::Unavailable; +} + +inline constexpr Trait common_trait_impl(Trait result) +{ + return result; +} + +template +inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts) +{ + return static_cast(t) > static_cast(result) ? common_trait_impl(t, ts...) + : common_trait_impl(result, ts...); +} + +template +inline constexpr Trait common_trait(Traits... ts) +{ + return common_trait_impl(Trait::TriviallyAvailable, ts...); +} + +template +struct traits +{ + static constexpr Trait copy_constructible_trait = common_trait( + trait()...); + + static constexpr Trait move_constructible_trait = common_trait( + trait()...); + + static constexpr Trait copy_assignable_trait = + common_trait(copy_constructible_trait, + trait()...); + + static constexpr Trait move_assignable_trait = + common_trait(move_constructible_trait, + trait()...); + + static constexpr Trait destructible_trait = + common_trait(trait()...); +}; +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/decay.h b/api/include/opentelemetry/nostd/detail/decay.h new file mode 100644 index 0000000000..14df2dcd4a --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/decay.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template< class T > +using decay_t = typename std::decay::type; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/find_index.h b/api/include/opentelemetry/nostd/detail/find_index.h new file mode 100644 index 0000000000..a750f94fef --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/find_index.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +constexpr std::size_t not_found = static_cast(-1); +constexpr std::size_t ambiguous = static_cast(-2); + +inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t) +{ + return result; +} + +template +inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t idx, bool b, Bs... bs) +{ + return b ? (result != not_found ? ambiguous : find_index_impl(idx, idx + 1, bs...)) + : find_index_impl(result, idx + 1, bs...); +} + +template +inline constexpr std::size_t find_index() +{ + return find_index_impl(not_found, 0, std::is_same::value...); +} + +template +using find_index_sfinae_impl = + enable_if_t>; + +template +using find_index_sfinae = find_index_sfinae_impl()>; + +template +struct find_index_checked_impl : std::integral_constant +{ + static_assert(I != not_found, "the specified type is not found."); + static_assert(I != ambiguous, "the specified type is ambiguous."); +}; + +template +using find_index_checked = find_index_checked_impl()>; +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h new file mode 100644 index 0000000000..9858e6b6f0 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include + +#include "opentelemetry/nostd/detail/decay.h" +#include "opentelemetry/version.h" + +#define MPARK_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ + +template +struct is_reference_wrapper : std::false_type +{}; + +template +struct is_reference_wrapper> : std::true_type +{}; + +template +struct Invoke; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((std::forward(arg).*pmf)(std::forward(args)...)) +}; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN((std::forward(arg).get().*pmf)(std::forward(args)...)) +}; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) + MPARK_RETURN(((*std::forward(arg)).*pmf)(std::forward(args)...)) +}; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(std::forward(arg).*pmo) +}; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN(std::forward(arg).get().*pmo) +}; + +template <> +struct Invoke +{ + template + inline static constexpr auto invoke(R T::*pmo, Arg &&arg) + MPARK_RETURN((*std::forward(arg)).*pmo) +}; + +template +inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) + MPARK_RETURN(Invoke::value, + (std::is_base_of>::value + ? 0 + : is_reference_wrapper>::value ? 1 : 2)>:: + invoke(f, std::forward(arg), std::forward(args)...)) + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4100) +#endif + template + inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(std::forward(f)(std::forward(args)...)) +#ifdef _MSC_VER +# pragma warning(pop) +#endif +} // namespace detail + +template +inline constexpr auto invoke(F &&f, Args &&... args) + MPARK_RETURN(detail::invoke(std::forward(f), std::forward(args)...)) +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + +#undef MPARK_RETURN diff --git a/api/include/opentelemetry/nostd/in_place.hpp b/api/include/opentelemetry/nostd/in_place.hpp index 73a0cdaaad..56cae13113 100644 --- a/api/include/opentelemetry/nostd/in_place.hpp +++ b/api/include/opentelemetry/nostd/in_place.hpp @@ -5,15 +5,14 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) -#pragma once - -#include "opentelemetry/version.h" +#ifndef MPARK_IN_PLACE_HPP +#define MPARK_IN_PLACE_HPP #include -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ +#include "config.hpp" + +namespace mpark { struct in_place_t { explicit in_place_t() = default; }; @@ -23,5 +22,14 @@ namespace nostd template struct in_place_type_t { explicit in_place_type_t() = default; }; -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE +#ifdef MPARK_VARIABLE_TEMPLATES + constexpr in_place_t in_place{}; + + template constexpr in_place_index_t in_place_index{}; + + template constexpr in_place_type_t in_place_type{}; +#endif + +} // namespace mpark + +#endif // MPARK_IN_PLACE_HPP diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index 1a8bcb9e99..c719a1be0f 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -2,12 +2,21 @@ #include #include +#include +#include "opentelemetry/nostd/detail/decay.h" +#include "opentelemetry/nostd/detail/invoke.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { +/** + * Back port of std::enable_if_t + */ +template +using enable_if_t = typename std::enable_if::value; + /** * Back port of std::data * @@ -102,5 +111,31 @@ using make_index_sequence = typename detail::make_index_sequence_impl::type; */ template using index_sequence_for = make_index_sequence; + +/** + * Back port of std::in_place_t + */ +struct in_place_t +{ + explicit in_place_t() = default; +}; + +/** + * Back port of std::in_place_index_t + */ +template +struct in_place_index_t +{ + explicit in_place_index_t() = default; +}; + +/** + * Back port of std::in_place_type_t + */ +template +struct in_place_type_t +{ + explicit in_place_type_t() = default; +}; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 0862695eb5..854b2cbf80 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -1,5 +1,326 @@ #pragma once +#include +#include + +#include "opentelemetry/nostd/detail/common_trait.h" +#include "opentelemetry/nostd/detail/find_index.h" #include "opentelemetry/nostd/detail/type_pack_element.h" -#include "opentelemetry/nostd/detail/variant_size.h" #include "opentelemetry/nostd/detail/variant_alternative.h" +#include "opentelemetry/nostd/detail/variant_fwd.h" +#include "opentelemetry/nostd/detail/variant_size.h" +#include "opentelemetry/nostd/utility.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ + +#define AUTO auto +#define AUTO_RETURN(...) \ + -> decay_t { return __VA_ARGS__; } + +#define AUTO_REFREF auto +#define AUTO_REFREF_RETURN(...) \ + ->decltype((__VA_ARGS__)) \ + { \ + static_assert(std::is_reference::value, ""); \ + return __VA_ARGS__; \ + } + +#define DECLTYPE_AUTO auto +#define DECLTYPE_AUTO_RETURN(...) \ + ->decltype(__VA_ARGS__) { return __VA_ARGS__; } + +class bad_variant_access : public std::exception +{ +public: + virtual const char *what() const noexcept override { return "bad_variant_access"; } +}; + +[[noreturn]] inline void throw_bad_variant_access() +{ +#if __EXCEPTIONS + throw bad_variant_access{}; +#else + std::terminate(); +#endif +} + +namespace detail +{ +namespace access +{ + +struct recursive_union +{ + template + struct get_alt_impl + { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v).tail_)) + }; + + template + struct get_alt_impl<0, Dummy> + { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(std::forward(v).head_) + }; + + template + inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) + AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v))) +}; + +struct base +{ + template + inline static constexpr AUTO_REFREF get_alt(V &&v) +#ifdef _MSC_VER + AUTO_REFREF_RETURN(recursive_union::get_alt(std::forward(v).data_, in_place_index_t{})) +#else + AUTO_REFREF_RETURN(recursive_union::get_alt(data(std::forward(v)), in_place_index_t{})) +#endif +}; + +struct variant +{ + template + inline static constexpr AUTO_REFREF get_alt(V &&v) + AUTO_REFREF_RETURN(base::get_alt(std::forward(v).impl_)) +}; +} // namespace access +} // namespace detail + +namespace detail +{ +namespace visitation +{ + +struct base +{ + template + using dispatch_result_t = decltype( + invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); + + template + struct expected + { + template + inline static constexpr bool but_got() + { + return std::is_same::value; + } + }; + + template + struct visit_return_type_check + { + static_assert(expected::template but_got(), + "`visit` requires the visitor to have a single return type"); + + template + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Alts &&... alts) + DECLTYPE_AUTO_RETURN(invoke(std::forward(visitor), std::forward(alts)...)) + }; + + template + inline static constexpr const T &at(const T &elem) noexcept + { + return elem; + } + +#if 0 + template + inline static constexpr const lib::remove_all_extents_t &at(const std::array &elems, + std::size_t i, + Is... is) noexcept + { + return at(elems[i], is...); + } + + template + inline static constexpr lib::array, sizeof...(Fs) + 1> make_farray(F &&f, + Fs &&... fs) + { + return {{std::forward(f), std::forward(fs)...}}; + } + + template + struct make_fmatrix_impl + { + + template + inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) + { + using Expected = dispatch_result_t; + using Actual = decltype( + lib::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + return visit_return_type_check::invoke( + std::forward(f), access::base::get_alt(std::forward(vs))...); + } + + template + struct impl; + + template + struct impl> + { + inline constexpr AUTO operator()() const AUTO_RETURN(&dispatch) + }; + + template + struct impl, Ls...> + { + inline constexpr AUTO operator()() const + AUTO_RETURN(make_farray(impl, Ls...>{}()...)) + }; + }; + + template + inline static constexpr AUTO make_fmatrix() + AUTO_RETURN(typename make_fmatrix_impl::template impl< + lib::index_sequence<>, + lib::make_index_sequence::size()>...>{}()) + + template + struct make_fdiagonal_impl + { + template + inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) + { + using Expected = dispatch_result_t; + using Actual = decltype( + lib::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + return visit_return_type_check::invoke( + std::forward(f), access::base::get_alt(std::forward(vs))...); + } + + template + inline static constexpr AUTO impl(lib::index_sequence) + AUTO_RETURN(make_farray(&dispatch...)) + }; + + template + inline static constexpr auto make_fdiagonal() -> decltype( + make_fdiagonal_impl::impl(lib::make_index_sequence::size()>{})) + { + static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, + "all of the variants must be the same size."); + return make_fdiagonal_impl::impl( + lib::make_index_sequence::size()>{}); + } +}; + +#if !defined(MPARK_VARIANT_SWITCH_VISIT) && (!defined(_MSC_VER) || _MSC_VER >= 1910) +template +using fmatrix_t = decltype(base::make_fmatrix()); + +template +struct fmatrix +{ + static constexpr fmatrix_t value = base::make_fmatrix(); +}; + +template +constexpr fmatrix_t fmatrix::value; + +template +using fdiagonal_t = decltype(base::make_fdiagonal()); + +template +struct fdiagonal +{ + static constexpr fdiagonal_t value = base::make_fdiagonal(); +}; + +template +constexpr fdiagonal_t fdiagonal::value; +#endif + +struct alt +{ + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN( + base::at(base::make_fmatrix(vs)))...>(), + vs.index()...)(std::forward(visitor), as_base(std::forward(vs))...)) + + template + inline static constexpr DECLTYPE_AUTO + visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( + base::at(base::make_fdiagonal(vs)))...>(), + index)(std::forward(visitor), as_base(std::forward(vs))...)) +}; + +struct variant +{ +private: + template + struct visitor + { + template + inline static constexpr bool does_not_handle() + { + return lib::is_invocable::value; + } + }; + + template + struct visit_exhaustiveness_check + { + static_assert(visitor::template does_not_handle(), + "`visit` requires the visitor to be exhaustive."); + + inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) + DECLTYPE_AUTO_RETURN(lib::invoke(std::forward(visitor), + std::forward(values)...)) + }; + + template + struct value_visitor + { + Visitor &&visitor_; + + template + inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const DECLTYPE_AUTO_RETURN( + visit_exhaustiveness_check(alts).value))...>::invoke( + std::forward(visitor_), + std::forward(alts).value...)) + }; + + template + inline static constexpr AUTO make_value_visitor(Visitor &&visitor) + AUTO_RETURN(value_visitor{std::forward(visitor)}) + + public + : template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN(alt::visit_alt(std::forward(visitor), + std::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO + visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( + alt::visit_alt_at(index, std::forward(visitor), std::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN(visit_alt(make_value_visitor(std::forward(visitor)), + std::forward(vs)...)) + + template + inline static constexpr DECLTYPE_AUTO + visit_value_at(std::size_t index, Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN(visit_alt_at(index, + make_value_visitor(std::forward(visitor)), + std::forward(vs)...)) +#endif +}; +} // namespace visitation +} // namespace detail + +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.hpp b/api/include/opentelemetry/nostd/variant.hpp index 19c51f6e6f..423a789bf8 100644 --- a/api/include/opentelemetry/nostd/variant.hpp +++ b/api/include/opentelemetry/nostd/variant.hpp @@ -7,192 +7,6 @@ #pragma once -/* - variant synopsis - -namespace std { - - // 20.7.2, class template variant - template - class variant { - public: - - // 20.7.2.1, constructors - constexpr variant() noexcept(see below); - variant(const variant&); - variant(variant&&) noexcept(see below); - - template constexpr variant(T&&) noexcept(see below); - - template - constexpr explicit variant(in_place_type_t, Args&&...); - - template - constexpr explicit variant( - in_place_type_t, initializer_list, Args&&...); - - template - constexpr explicit variant(in_place_index_t, Args&&...); - - template - constexpr explicit variant( - in_place_index_t, initializer_list, Args&&...); - - // 20.7.2.2, destructor - ~variant(); - - // 20.7.2.3, assignment - variant& operator=(const variant&); - variant& operator=(variant&&) noexcept(see below); - - template variant& operator=(T&&) noexcept(see below); - - // 20.7.2.4, modifiers - template - T& emplace(Args&&...); - - template - T& emplace(initializer_list, Args&&...); - - template - variant_alternative& emplace(Args&&...); - - template - variant_alternative& emplace(initializer_list, Args&&...); - - // 20.7.2.5, value status - constexpr bool valueless_by_exception() const noexcept; - constexpr size_t index() const noexcept; - - // 20.7.2.6, swap - void swap(variant&) noexcept(see below); - }; - - // 20.7.3, variant helper classes - template struct variant_size; // undefined - - template - constexpr size_t variant_size_v = variant_size::value; - - template struct variant_size; - template struct variant_size; - template struct variant_size; - - template - struct variant_size>; - - template struct variant_alternative; // undefined - - template - using variant_alternative_t = typename variant_alternative::type; - - template struct variant_alternative; - template struct variant_alternative; - template struct variant_alternative; - - template - struct variant_alternative>; - - constexpr size_t variant_npos = -1; - - // 20.7.4, value access - template - constexpr bool holds_alternative(const variant&) noexcept; - - template - constexpr variant_alternative_t>& - get(variant&); - - template - constexpr variant_alternative_t>&& - get(variant&&); - - template - constexpr variant_alternative_t> const& - get(const variant&); - - template - constexpr variant_alternative_t> const&& - get(const variant&&); - - template - constexpr T& get(variant&); - - template - constexpr T&& get(variant&&); - - template - constexpr const T& get(const variant&); - - template - constexpr const T&& get(const variant&&); - - template - constexpr add_pointer_t>> - get_if(variant*) noexcept; - - template - constexpr add_pointer_t>> - get_if(const variant*) noexcept; - - template - constexpr add_pointer_t - get_if(variant*) noexcept; - - template - constexpr add_pointer_t - get_if(const variant*) noexcept; - - // 20.7.5, relational operators - template - constexpr bool operator==(const variant&, const variant&); - - template - constexpr bool operator!=(const variant&, const variant&); - - template - constexpr bool operator<(const variant&, const variant&); - - template - constexpr bool operator>(const variant&, const variant&); - - template - constexpr bool operator<=(const variant&, const variant&); - - template - constexpr bool operator>=(const variant&, const variant&); - - // 20.7.6, visitation - template - constexpr see below visit(Visitor&&, Variants&&...); - - // 20.7.7, class monostate - struct monostate; - - // 20.7.8, monostate relational operators - constexpr bool operator<(monostate, monostate) noexcept; - constexpr bool operator>(monostate, monostate) noexcept; - constexpr bool operator<=(monostate, monostate) noexcept; - constexpr bool operator>=(monostate, monostate) noexcept; - constexpr bool operator==(monostate, monostate) noexcept; - constexpr bool operator!=(monostate, monostate) noexcept; - - // 20.7.9, specialized algorithms - template - void swap(variant&, variant&) noexcept(see below); - - // 20.7.10, class bad_variant_access - class bad_variant_access; - - // 20.7.11, hash support - template struct hash; - template struct hash>; - template <> struct hash; - -} // namespace std - -*/ - #include #include #include @@ -212,19 +26,6 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -#ifdef MPARK_RETURN_TYPE_DEDUCTION - -#define AUTO auto -#define AUTO_RETURN(...) { return __VA_ARGS__; } - -#define AUTO_REFREF auto && -#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } - -#define DECLTYPE_AUTO decltype(auto) -#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } - -#else - #define AUTO auto #define AUTO_RETURN(...) \ -> lib::decay_t { return __VA_ARGS__; } @@ -240,8 +41,6 @@ namespace nostd #define DECLTYPE_AUTO_RETURN(...) \ -> decltype(__VA_ARGS__) { return __VA_ARGS__; } -#endif - class bad_variant_access : public std::exception { public: virtual const char *what() const noexcept override { return "bad_variant_access"; } @@ -447,10 +246,6 @@ namespace nostd namespace visitation { -#if defined(MPARK_CPP14_CONSTEXPR) && !defined(_MSC_VER) -#define MPARK_VARIANT_SWITCH_VISIT -#endif - struct base { template using dispatch_result_t = decltype( @@ -478,176 +273,6 @@ namespace nostd lib::forward(alts)...)) }; -#ifdef MPARK_VARIANT_SWITCH_VISIT - template - struct dispatcher; - - template - struct dispatcher { - template - MPARK_ALWAYS_INLINE static constexpr R dispatch( - F &&, typename ITs::type &&..., Vs &&...) { - MPARK_BUILTIN_UNREACHABLE; - } - - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) { - MPARK_BUILTIN_UNREACHABLE; - } - - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t, - F &&, - Vs &&...) { - MPARK_BUILTIN_UNREACHABLE; - } - }; - - template - struct dispatcher { - template - MPARK_ALWAYS_INLINE static constexpr R dispatch( - F &&f, typename ITs::type &&... visited_vs) { - using Expected = R; - using Actual = decltype(lib::invoke( - lib::forward(f), - access::base::get_alt( - lib::forward(visited_vs))...)); - return visit_return_type_check::invoke( - lib::forward(f), - access::base::get_alt( - lib::forward(visited_vs))...); - } - - template - MPARK_ALWAYS_INLINE static constexpr R dispatch( - F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) { -#define MPARK_DISPATCH(I) \ - dispatcher<(I < lib::decay_t::size()), \ - R, \ - ITs..., \ - lib::indexed_type>:: \ - template dispatch<0>(lib::forward(f), \ - lib::forward(visited_vs)..., \ - lib::forward(v), \ - lib::forward(vs)...) - -#define MPARK_DEFAULT(I) \ - dispatcher<(I < lib::decay_t::size()), R, ITs...>::template dispatch( \ - lib::forward(f), \ - lib::forward(visited_vs)..., \ - lib::forward(v), \ - lib::forward(vs)...) - - switch (v.index()) { - case B + 0: return MPARK_DISPATCH(B + 0); - case B + 1: return MPARK_DISPATCH(B + 1); - case B + 2: return MPARK_DISPATCH(B + 2); - case B + 3: return MPARK_DISPATCH(B + 3); - case B + 4: return MPARK_DISPATCH(B + 4); - case B + 5: return MPARK_DISPATCH(B + 5); - case B + 6: return MPARK_DISPATCH(B + 6); - case B + 7: return MPARK_DISPATCH(B + 7); - case B + 8: return MPARK_DISPATCH(B + 8); - case B + 9: return MPARK_DISPATCH(B + 9); - case B + 10: return MPARK_DISPATCH(B + 10); - case B + 11: return MPARK_DISPATCH(B + 11); - case B + 12: return MPARK_DISPATCH(B + 12); - case B + 13: return MPARK_DISPATCH(B + 13); - case B + 14: return MPARK_DISPATCH(B + 14); - case B + 15: return MPARK_DISPATCH(B + 15); - case B + 16: return MPARK_DISPATCH(B + 16); - case B + 17: return MPARK_DISPATCH(B + 17); - case B + 18: return MPARK_DISPATCH(B + 18); - case B + 19: return MPARK_DISPATCH(B + 19); - case B + 20: return MPARK_DISPATCH(B + 20); - case B + 21: return MPARK_DISPATCH(B + 21); - case B + 22: return MPARK_DISPATCH(B + 22); - case B + 23: return MPARK_DISPATCH(B + 23); - case B + 24: return MPARK_DISPATCH(B + 24); - case B + 25: return MPARK_DISPATCH(B + 25); - case B + 26: return MPARK_DISPATCH(B + 26); - case B + 27: return MPARK_DISPATCH(B + 27); - case B + 28: return MPARK_DISPATCH(B + 28); - case B + 29: return MPARK_DISPATCH(B + 29); - case B + 30: return MPARK_DISPATCH(B + 30); - case B + 31: return MPARK_DISPATCH(B + 31); - default: return MPARK_DEFAULT(B + 32); - } - -#undef MPARK_DEFAULT -#undef MPARK_DISPATCH - } - - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_case(F &&f, - Vs &&... vs) { - using Expected = R; - using Actual = decltype( - lib::invoke(lib::forward(f), - access::base::get_alt(lib::forward(vs))...)); - return visit_return_type_check::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...); - } - - template - MPARK_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index, - F &&f, - V &&v, - Vs &&... vs) { - static_assert(lib::all<(lib::decay_t::size() == - lib::decay_t::size())...>::value, - "all of the variants must be the same size."); -#define MPARK_DISPATCH_AT(I) \ - dispatcher<(I < lib::decay_t::size()), R>::template dispatch_case( \ - lib::forward(f), lib::forward(v), lib::forward(vs)...) - -#define MPARK_DEFAULT(I) \ - dispatcher<(I < lib::decay_t::size()), R>::template dispatch_at( \ - index, lib::forward(f), lib::forward(v), lib::forward(vs)...) - - switch (index) { - case B + 0: return MPARK_DISPATCH_AT(B + 0); - case B + 1: return MPARK_DISPATCH_AT(B + 1); - case B + 2: return MPARK_DISPATCH_AT(B + 2); - case B + 3: return MPARK_DISPATCH_AT(B + 3); - case B + 4: return MPARK_DISPATCH_AT(B + 4); - case B + 5: return MPARK_DISPATCH_AT(B + 5); - case B + 6: return MPARK_DISPATCH_AT(B + 6); - case B + 7: return MPARK_DISPATCH_AT(B + 7); - case B + 8: return MPARK_DISPATCH_AT(B + 8); - case B + 9: return MPARK_DISPATCH_AT(B + 9); - case B + 10: return MPARK_DISPATCH_AT(B + 10); - case B + 11: return MPARK_DISPATCH_AT(B + 11); - case B + 12: return MPARK_DISPATCH_AT(B + 12); - case B + 13: return MPARK_DISPATCH_AT(B + 13); - case B + 14: return MPARK_DISPATCH_AT(B + 14); - case B + 15: return MPARK_DISPATCH_AT(B + 15); - case B + 16: return MPARK_DISPATCH_AT(B + 16); - case B + 17: return MPARK_DISPATCH_AT(B + 17); - case B + 18: return MPARK_DISPATCH_AT(B + 18); - case B + 19: return MPARK_DISPATCH_AT(B + 19); - case B + 20: return MPARK_DISPATCH_AT(B + 20); - case B + 21: return MPARK_DISPATCH_AT(B + 21); - case B + 22: return MPARK_DISPATCH_AT(B + 22); - case B + 23: return MPARK_DISPATCH_AT(B + 23); - case B + 24: return MPARK_DISPATCH_AT(B + 24); - case B + 25: return MPARK_DISPATCH_AT(B + 25); - case B + 26: return MPARK_DISPATCH_AT(B + 26); - case B + 27: return MPARK_DISPATCH_AT(B + 27); - case B + 28: return MPARK_DISPATCH_AT(B + 28); - case B + 29: return MPARK_DISPATCH_AT(B + 29); - case B + 30: return MPARK_DISPATCH_AT(B + 30); - case B + 31: return MPARK_DISPATCH_AT(B + 31); - default: return MPARK_DEFAULT(B + 32); - } - -#undef MPARK_DEFAULT -#undef MPARK_DISPATCH_AT - } - }; -#else template inline static constexpr const T &at(const T &elem) noexcept { return elem; @@ -733,7 +358,6 @@ namespace nostd return make_fdiagonal_impl::impl( lib::make_index_sequence::size()>{}); } -#endif }; #if !defined(MPARK_VARIANT_SWITCH_VISIT) && \ @@ -767,56 +391,21 @@ namespace nostd template inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) -#ifdef MPARK_VARIANT_SWITCH_VISIT - DECLTYPE_AUTO_RETURN( - base::dispatcher< - true, - base::dispatch_result_t(vs)))...>>:: - template dispatch<0>(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#elif !defined(_MSC_VER) || _MSC_VER >= 1910 - DECLTYPE_AUTO_RETURN(base::at( - fmatrix(vs)))...>::value, - vs.index()...)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#else DECLTYPE_AUTO_RETURN(base::at( base::make_fmatrix(vs)))...>(), vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) -#endif template inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) -#ifdef MPARK_VARIANT_SWITCH_VISIT - DECLTYPE_AUTO_RETURN( - base::dispatcher< - true, - base::dispatch_result_t(vs)))...>>:: - template dispatch_at<0>(index, - lib::forward(visitor), - as_base(lib::forward(vs))...)) -#elif !defined(_MSC_VER) || _MSC_VER >= 1910 - DECLTYPE_AUTO_RETURN(base::at( - fdiagonal(vs)))...>::value, - index)(lib::forward(visitor), - as_base(lib::forward(vs))...)) -#else DECLTYPE_AUTO_RETURN(base::at( base::make_fdiagonal(vs)))...>(), index)(lib::forward(visitor), as_base(lib::forward(vs))...)) -#endif }; struct variant { From 998d1ed5f8b63e5502f17f5b8b6f13f394101e2b Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Tue, 31 Mar 2020 22:19:19 -0700 Subject: [PATCH 07/42] Fill out variant backport --- api/include/opentelemetry/nostd/detail/all.h | 18 ++++++ .../opentelemetry/nostd/detail/invoke.h | 56 ++++++++++++++++++- api/include/opentelemetry/nostd/detail/void.h | 14 +++++ api/include/opentelemetry/nostd/type_traits.h | 30 ++++++++++ api/include/opentelemetry/nostd/utility.h | 6 +- api/include/opentelemetry/nostd/variant.h | 47 ++++++++-------- 6 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 api/include/opentelemetry/nostd/detail/all.h create mode 100644 api/include/opentelemetry/nostd/detail/void.h create mode 100644 api/include/opentelemetry/nostd/type_traits.h diff --git a/api/include/opentelemetry/nostd/detail/all.h b/api/include/opentelemetry/nostd/detail/all.h new file mode 100644 index 0000000000..dc12a5a5f9 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/all.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +template +using all = std::is_same, integer_sequence>; + +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h index 9858e6b6f0..c744e2e238 100644 --- a/api/include/opentelemetry/nostd/detail/invoke.h +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -4,10 +4,11 @@ #include #include "opentelemetry/nostd/detail/decay.h" +#include "opentelemetry/nostd/detail/void.h" #include "opentelemetry/version.h" #define MPARK_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd @@ -96,7 +97,58 @@ inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) template inline constexpr auto invoke(F &&f, Args &&... args) - MPARK_RETURN(detail::invoke(std::forward(f), std::forward(args)...)) + MPARK_RETURN(detail::invoke(std::forward(f), std::forward(args)...)); + +namespace detail +{ + + template + struct invoke_result + {}; + + template + struct invoke_result(), std::declval()...))>, + F, + Args...> + { + using type = decltype(invoke(std::declval(), std::declval()...)); + }; + +} // namespace detail + +template +using invoke_result = detail::invoke_result; + +template +using invoke_result_t = typename invoke_result::type; + +namespace detail +{ + +template +struct is_invocable : std::false_type +{}; + +template +struct is_invocable>, F, Args...> : std::true_type +{}; + +template +struct is_invocable_r : std::false_type +{}; + +template +struct is_invocable_r>, R, F, Args...> + : std::is_convertible, R> +{}; + +} // namespace detail + +template +using is_invocable = detail::is_invocable; + +template +using is_invocable_r = detail::is_invocable_r; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/void.h b/api/include/opentelemetry/nostd/detail/void.h new file mode 100644 index 0000000000..63c548fb72 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/void.h @@ -0,0 +1,14 @@ +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +/** + * Back port of std::void_t + */ +template +using void_t = void; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h new file mode 100644 index 0000000000..446d12cb3a --- /dev/null +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/detail/void.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +/** + * Back port of std::remove_all_extents + */ +template +struct remove_all_extents +{ + using type = T; +}; + +template +struct remove_all_extents> : remove_all_extents +{}; + +/** + * Back port of std::remove_all_extents_t + */ +template +using remove_all_extents_t = typename remove_all_extents::type; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index c719a1be0f..8672523f71 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -91,10 +91,12 @@ struct index_sequence_push_back, I> { using type = index_sequence; }; +template +using index_sequence_push_back_t = typename index_sequence_push_back::type; + template struct make_index_sequence_impl { - using type = typename index_sequence_push_back::type, - N - 1>::type; + using type = index_sequence_push_back_t::type, N - 1>; }; template <> diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 854b2cbf80..d4b8d58c2b 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -3,6 +3,7 @@ #include #include +#include "opentelemetry/nostd/detail/all.h" #include "opentelemetry/nostd/detail/common_trait.h" #include "opentelemetry/nostd/detail/find_index.h" #include "opentelemetry/nostd/detail/type_pack_element.h" @@ -10,6 +11,7 @@ #include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/nostd/detail/variant_size.h" #include "opentelemetry/nostd/utility.h" +#include "opentelemetry/nostd/type_traits.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd @@ -132,18 +134,16 @@ struct base return elem; } -#if 0 template - inline static constexpr const lib::remove_all_extents_t &at(const std::array &elems, - std::size_t i, - Is... is) noexcept + inline static constexpr const remove_all_extents_t &at(const std::array &elems, + std::size_t i, + Is... is) noexcept { return at(elems[i], is...); } template - inline static constexpr lib::array, sizeof...(Fs) + 1> make_farray(F &&f, - Fs &&... fs) + inline static constexpr std::array, sizeof...(Fs) + 1> make_farray(F &&f, Fs &&... fs) { return {{std::forward(f), std::forward(fs)...}}; } @@ -157,7 +157,7 @@ struct base { using Expected = dispatch_result_t; using Actual = decltype( - lib::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -166,24 +166,25 @@ struct base struct impl; template - struct impl> + struct impl> { inline constexpr AUTO operator()() const AUTO_RETURN(&dispatch) }; template - struct impl, Ls...> + struct impl, Ls...> { inline constexpr AUTO operator()() const - AUTO_RETURN(make_farray(impl, Ls...>{}()...)) + AUTO_RETURN(make_farray(impl, Ls...>{}()...)) }; }; + template inline static constexpr AUTO make_fmatrix() AUTO_RETURN(typename make_fmatrix_impl::template impl< - lib::index_sequence<>, - lib::make_index_sequence::size()>...>{}()) + index_sequence<>, + make_index_sequence::size()>...>{}()) template struct make_fdiagonal_impl @@ -192,29 +193,30 @@ struct base inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) { using Expected = dispatch_result_t; - using Actual = decltype( - lib::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + using Actual = + decltype(invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } template - inline static constexpr AUTO impl(lib::index_sequence) + inline static constexpr AUTO impl(index_sequence) AUTO_RETURN(make_farray(&dispatch...)) }; template inline static constexpr auto make_fdiagonal() -> decltype( - make_fdiagonal_impl::impl(lib::make_index_sequence::size()>{})) + make_fdiagonal_impl::impl(make_index_sequence::size()>{})) { - static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, + static_assert(all<(decay_t::size() == decay_t::size())...>::value, "all of the variants must be the same size."); return make_fdiagonal_impl::impl( - lib::make_index_sequence::size()>{}); + make_index_sequence::size()>{}); } }; -#if !defined(MPARK_VARIANT_SWITCH_VISIT) && (!defined(_MSC_VER) || _MSC_VER >= 1910) + +#if !defined(_MSC_VER) || _MSC_VER >= 1910 template using fmatrix_t = decltype(base::make_fmatrix()); @@ -264,7 +266,7 @@ struct variant template inline static constexpr bool does_not_handle() { - return lib::is_invocable::value; + return is_invocable::value; } }; @@ -275,8 +277,8 @@ struct variant "`visit` requires the visitor to be exhaustive."); inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) - DECLTYPE_AUTO_RETURN(lib::invoke(std::forward(visitor), - std::forward(values)...)) + DECLTYPE_AUTO_RETURN(invoke(std::forward(visitor), + std::forward(values)...)) }; template @@ -317,7 +319,6 @@ struct variant DECLTYPE_AUTO_RETURN(visit_alt_at(index, make_value_visitor(std::forward(visitor)), std::forward(vs)...)) -#endif }; } // namespace visitation } // namespace detail From 1515e0868de8f748d16579f5be47728a1a638a82 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 15:55:07 -0700 Subject: [PATCH 08/42] Fill out variant back port --- .../nostd/detail/recursive_union.h | 118 ++++++ .../nostd/detail/{common_trait.h => trait.h} | 0 .../opentelemetry/nostd/detail/valueless.h | 10 + api/include/opentelemetry/nostd/utility.h | 6 + api/include/opentelemetry/nostd/variant.h | 372 +++++++++++++++--- 5 files changed, 459 insertions(+), 47 deletions(-) create mode 100644 api/include/opentelemetry/nostd/detail/recursive_union.h rename api/include/opentelemetry/nostd/detail/{common_trait.h => trait.h} (100%) create mode 100644 api/include/opentelemetry/nostd/detail/valueless.h diff --git a/api/include/opentelemetry/nostd/detail/recursive_union.h b/api/include/opentelemetry/nostd/detail/recursive_union.h new file mode 100644 index 0000000000..2a3cf53643 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/recursive_union.h @@ -0,0 +1,118 @@ +#pragma once + +#include +#include + +#include "opentelemetry/nostd/detail/trait.h" +#include "opentelemetry/nostd/detail/valueless.h" +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/version.h" + +#define AUTO_REFREF_RETURN(...) \ + ->decltype((__VA_ARGS__)) \ + { \ + static_assert(std::is_reference::value, ""); \ + return __VA_ARGS__; \ + } + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +namespace access +{ +struct recursive_union +{ + template + struct get_alt_impl + { + template + inline constexpr auto operator()(V &&v) const + AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v).tail_)) + }; + + template + struct get_alt_impl<0, Dummy> + { + template + inline constexpr auto operator()(V &&v) const + AUTO_REFREF_RETURN(std::forward(v).head_) + }; + + template + inline static constexpr auto get_alt(V &&v, in_place_index_t) + AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v))) +}; +} // namespace access + +template +struct alt +{ + using value_type = T; + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4244) +#endif + template + inline explicit constexpr alt(in_place_t, Args &&... args) : value(std::forward(args)...) + {} +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + T value; +}; + +template +union recursive_union; + +template +union recursive_union +{}; + +#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ + template \ + union recursive_union \ + { \ + public: \ + inline explicit constexpr recursive_union(valueless_t) noexcept : dummy_{} {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t<0>, Args &&... args) \ + : head_(in_place_t{}, std::forward(args)...) \ + {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t, Args &&... args) \ + : tail_(in_place_index_t{}, std::forward(args)...) \ + {} \ + \ + recursive_union(const recursive_union &) = default; \ + recursive_union(recursive_union &&) = default; \ + \ + destructor \ + \ + recursive_union & \ + operator=(const recursive_union &) = default; \ + recursive_union &operator=(recursive_union &&) = default; \ + \ + private: \ + char dummy_; \ + alt head_; \ + recursive_union tail_; \ + \ + friend struct access::recursive_union; \ + } + +MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;); +MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){}); +MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); + +#undef MPARK_VARIANT_RECURSIVE_UNION +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + +#undef AUTO_REFREF_RETURN diff --git a/api/include/opentelemetry/nostd/detail/common_trait.h b/api/include/opentelemetry/nostd/detail/trait.h similarity index 100% rename from api/include/opentelemetry/nostd/detail/common_trait.h rename to api/include/opentelemetry/nostd/detail/trait.h diff --git a/api/include/opentelemetry/nostd/detail/valueless.h b/api/include/opentelemetry/nostd/detail/valueless.h new file mode 100644 index 0000000000..8de535f4e8 --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/valueless.h @@ -0,0 +1,10 @@ +#pragma once + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +struct valueless_t {}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index 8672523f71..ead2b13755 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -63,6 +63,12 @@ size_t size(T (&array)[N]) noexcept return N; } +/** + * Back port of std::bool_constant + */ +template +using bool_constant = std::integral_constant; + /** * Back port of std::integer_sequence */ diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index d4b8d58c2b..a38ec9b1b2 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -2,24 +2,23 @@ #include #include +#include #include "opentelemetry/nostd/detail/all.h" -#include "opentelemetry/nostd/detail/common_trait.h" #include "opentelemetry/nostd/detail/find_index.h" +#include "opentelemetry/nostd/detail/recursive_union.h" +#include "opentelemetry/nostd/detail/trait.h" #include "opentelemetry/nostd/detail/type_pack_element.h" #include "opentelemetry/nostd/detail/variant_alternative.h" #include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/nostd/detail/variant_size.h" -#include "opentelemetry/nostd/utility.h" #include "opentelemetry/nostd/type_traits.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/version.h" #define AUTO auto #define AUTO_RETURN(...) \ - -> decay_t { return __VA_ARGS__; } + ->decay_t { return __VA_ARGS__; } #define AUTO_REFREF auto #define AUTO_REFREF_RETURN(...) \ @@ -33,6 +32,11 @@ namespace nostd #define DECLTYPE_AUTO_RETURN(...) \ ->decltype(__VA_ARGS__) { return __VA_ARGS__; } +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +constexpr std::size_t variant_npos = static_cast(-1); + class bad_variant_access : public std::exception { public: @@ -52,30 +56,6 @@ namespace detail { namespace access { - -struct recursive_union -{ - template - struct get_alt_impl - { - template - inline constexpr AUTO_REFREF operator()(V &&v) const - AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v).tail_)) - }; - - template - struct get_alt_impl<0, Dummy> - { - template - inline constexpr AUTO_REFREF operator()(V &&v) const - AUTO_REFREF_RETURN(std::forward(v).head_) - }; - - template - inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) - AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v))) -}; - struct base { template @@ -104,8 +84,8 @@ namespace visitation struct base { template - using dispatch_result_t = decltype( - invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); + using dispatch_result_t = + decltype(invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); template struct expected @@ -156,8 +136,8 @@ struct base inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) { using Expected = dispatch_result_t; - using Actual = decltype( - invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + using Actual = + decltype(invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -179,15 +159,13 @@ struct base }; }; - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN(typename make_fmatrix_impl::template impl< - index_sequence<>, - make_index_sequence::size()>...>{}()) + inline static constexpr AUTO make_fmatrix() AUTO_RETURN( + typename make_fmatrix_impl:: + template impl, make_index_sequence::size()>...>{}()) - template - struct make_fdiagonal_impl + template + struct make_fdiagonal_impl { template inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) @@ -205,17 +183,15 @@ struct base }; template - inline static constexpr auto make_fdiagonal() -> decltype( - make_fdiagonal_impl::impl(make_index_sequence::size()>{})) + inline static constexpr auto make_fdiagonal() + -> decltype(make_fdiagonal_impl::impl(make_index_sequence::size()>{})) { static_assert(all<(decay_t::size() == decay_t::size())...>::value, "all of the variants must be the same size."); - return make_fdiagonal_impl::impl( - make_index_sequence::size()>{}); + return make_fdiagonal_impl::impl(make_index_sequence::size()>{}); } }; - #if !defined(_MSC_VER) || _MSC_VER >= 1910 template using fmatrix_t = decltype(base::make_fmatrix()); @@ -321,7 +297,309 @@ struct variant std::forward(vs)...)) }; } // namespace visitation + +template +using index_t = typename std::conditional< + sizeof...(Ts) < (std::numeric_limits::max)(), + unsigned char, + typename std::conditional::max)(), + unsigned short, + unsigned int>::type>::type; + +template +class base +{ +public: + inline explicit constexpr base(valueless_t tag) noexcept + : data_(tag), index_(static_cast>(-1)) + {} + + template + inline explicit constexpr base(in_place_index_t, Args &&... args) + : data_(in_place_index_t{}, std::forward(args)...), index_(I) + {} + + inline constexpr bool valueless_by_exception() const noexcept + { + return index_ == static_cast>(-1); + } + + inline constexpr std::size_t index() const noexcept + { + return valueless_by_exception() ? variant_npos : index_; + } + +protected: + using data_t = recursive_union; + + friend inline constexpr base &as_base(base &b) { return b; } + friend inline constexpr const base &as_base(const base &b) { return b; } + friend inline constexpr base &&as_base(base &&b) { return std::move(b); } + friend inline constexpr const base &&as_base(const base &&b) { return std::move(b); } + + friend inline constexpr data_t &data(base &b) { return b.data_; } + friend inline constexpr const data_t &data(const base &b) { return b.data_; } + friend inline constexpr data_t &&data(base &&b) { return std::move(b).data_; } + friend inline constexpr const data_t &&data(const base &&b) { return std::move(b).data_; } + + inline static constexpr std::size_t size() { return sizeof...(Ts); } + + data_t data_; + index_t index_; + + friend struct access::base; + friend struct visitation::base; +}; + +struct dtor +{ +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4100) +#endif + template + inline void operator()(Alt &alt) const noexcept + { + alt.~Alt(); + } +#ifdef _MSC_VER +# pragma warning(pop) +#endif +}; + +template +class destructor; + +#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ + template \ + class destructor, destructible_trait> : public base \ + { \ + using super = base; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + destructor(const destructor &) = default; \ + destructor(destructor &&) = default; \ + definition destructor &operator=(const destructor &) = default; \ + destructor &operator=(destructor &&) = default; \ + \ + protected: \ + destroy \ + } + +MPARK_VARIANT_DESTRUCTOR( + Trait::TriviallyAvailable, ~destructor() = default; + , inline void destroy() noexcept { this->index_ = static_cast>(-1); }); + +MPARK_VARIANT_DESTRUCTOR( + Trait::Available, + ~destructor() { destroy(); }, + inline void destroy() noexcept { + if (!this->valueless_by_exception()) + { + visitation::alt::visit_alt(dtor{}, *this); + } + this->index_ = static_cast>(-1); + }); + +MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; + , inline void destroy() noexcept = delete;); + +#undef MPARK_VARIANT_DESTRUCTOR + +template +class constructor : public destructor +{ + using super = destructor; + +public: + using super::super; + using super::operator=; + +protected: + struct ctor + { + template + inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const + { + constructor::construct_alt(lhs_alt, std::forward(rhs_alt).value); + } + }; + + template + inline static T &construct_alt(alt &a, Args &&... args) + { + auto *result = ::new (static_cast(std::addressof(a))) + alt(in_place_t{}, std::forward(args)...); + return result->value; + } + + template + inline static void generic_construct(constructor &lhs, Rhs &&rhs) + { + lhs.destroy(); + if (!rhs.valueless_by_exception()) + { + visitation::alt::visit_alt_at(rhs.index(), ctor{}, lhs, std::forward(rhs)); + lhs.index_ = rhs.index_; + } + } +}; + +template +class move_constructor; + +#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ + template \ + class move_constructor, move_constructible_trait> \ + : public constructor> \ + { \ + using super = constructor>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + move_constructor(const move_constructor &) = default; \ + definition ~move_constructor() = default; \ + move_constructor &operator=(const move_constructor &) = default; \ + move_constructor &operator=(move_constructor &&) = default; \ + } + +MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, + move_constructor(move_constructor &&that) = default;); + +MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Available, + move_constructor(move_constructor &&that) noexcept( + all::value...>::value) + : move_constructor(valueless_t{}) { this->generic_construct(*this, std::move(that)); }); + +MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor &&) = delete;); + +#undef MPARK_VARIANT_MOVE_CONSTRUCTOR + + template + class copy_constructor; + +#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ + template \ + class copy_constructor, copy_constructible_trait> \ + : public move_constructor> \ + { \ + using super = move_constructor>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + definition copy_constructor(copy_constructor &&) = default; \ + ~copy_constructor() = default; \ + copy_constructor &operator=(const copy_constructor &) = default; \ + copy_constructor &operator=(copy_constructor &&) = default; \ + } + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::TriviallyAvailable, + copy_constructor(const copy_constructor &that) = default;); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Available, + copy_constructor(const copy_constructor &that) + : copy_constructor(valueless_t{}) { + this->generic_construct(*this, that); + }); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Unavailable, + copy_constructor(const copy_constructor &) = delete;); + +#undef MPARK_VARIANT_COPY_CONSTRUCTOR + + template + class assignment : public copy_constructor { + using super = copy_constructor; + + public: + using super::super; + using super::operator=; + + template + inline /* auto & */ auto emplace(Args &&... args) + -> decltype(this->construct_alt(access::base::get_alt(*this), + std::forward(args)...)) { + this->destroy(); + auto &result = this->construct_alt(access::base::get_alt(*this), + std::forward(args)...); + this->index_ = I; + return result; + } + + protected: + template + struct assigner { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { + self->assign_alt(this_alt, std::forward(that_alt).value); + } + assignment *self; + }; + + template + inline void assign_alt(alt &a, Arg &&arg) { + if (this->index() == I) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + a.value = std::forward(arg); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } else { + struct { + void operator()(std::true_type) const { + this_->emplace(std::forward(arg_)); + } + void operator()(std::false_type) const { + this_->emplace(T(std::forward(arg_))); + } + assignment *this_; + Arg &&arg_; + } impl{this, std::forward(arg)}; + impl(bool_constant < std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value > {}); + } + } + + template + inline void generic_assign(That &&that) { + if (this->valueless_by_exception() && that.valueless_by_exception()) { + // do nothing. + } else if (that.valueless_by_exception()) { + this->destroy(); + } else { + visitation::alt::visit_alt_at( + that.index(), + assigner{this} + , + *this, + std::forward(that)); + } + } + }; } // namespace detail } // namespace nostd OPENTELEMETRY_END_NAMESPACE + +#undef AUTO +#undef AUTO_RETURN + +#undef AUTO_REFREF +#undef AUTO_REFREF_RETURN + +#undef DECLTYPE_AUTO +#undef DECLTYPE_AUTO_RETURN From 355bea0903bd21d5df2f2faf9fe78360540e37b8 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 18:39:46 -0700 Subject: [PATCH 09/42] Fill out variant backport --- .../opentelemetry/nostd/detail/find_index.h | 1 + api/include/opentelemetry/nostd/type_traits.h | 25 ++ api/include/opentelemetry/nostd/utility.h | 6 - api/include/opentelemetry/nostd/variant.h | 394 ++++++++++++++---- 4 files changed, 343 insertions(+), 83 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/find_index.h b/api/include/opentelemetry/nostd/detail/find_index.h index a750f94fef..e5fe9657c1 100644 --- a/api/include/opentelemetry/nostd/detail/find_index.h +++ b/api/include/opentelemetry/nostd/detail/find_index.h @@ -3,6 +3,7 @@ #include #include "opentelemetry/nostd/utility.h" +#include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index 446d12cb3a..f968d68d6f 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "opentelemetry/nostd/detail/void.h" @@ -8,6 +9,30 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { +/** + * Back port of std::enable_if_t + */ +template +using enable_if_t = typename std::enable_if::value; + +/** + * Back port of std::remove_const_t + */ +template +using remove_const_t = typename std::remove_const::type; + +/** + * Back port of std::remove_reference_t + */ +template +using remove_reference_t = typename std::remove_reference::type; + +/** + * Back port of std::remove_cvref_t + */ +template +using remove_cvref_t = typename std::remove_cv>::type; + /** * Back port of std::remove_all_extents */ diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index ead2b13755..27dcf2b6e8 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -11,12 +11,6 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -/** - * Back port of std::enable_if_t - */ -template -using enable_if_t = typename std::enable_if::value; - /** * Back port of std::data * diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index a38ec9b1b2..4653fce0dd 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -481,8 +481,8 @@ MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constru #undef MPARK_VARIANT_MOVE_CONSTRUCTOR - template - class copy_constructor; +template +class copy_constructor; #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ template \ @@ -501,95 +501,335 @@ MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constru copy_constructor &operator=(copy_constructor &&) = default; \ } - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::TriviallyAvailable, - copy_constructor(const copy_constructor &that) = default;); +MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable, + copy_constructor(const copy_constructor &that) = default;); - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Available, - copy_constructor(const copy_constructor &that) - : copy_constructor(valueless_t{}) { - this->generic_construct(*this, that); - }); +MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Available, copy_constructor(const copy_constructor &that) + : copy_constructor(valueless_t{}) { this->generic_construct(*this, that); }); - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Unavailable, - copy_constructor(const copy_constructor &) = delete;); +MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable, + copy_constructor(const copy_constructor &) = delete;); #undef MPARK_VARIANT_COPY_CONSTRUCTOR - template - class assignment : public copy_constructor { - using super = copy_constructor; - - public: - using super::super; - using super::operator=; - - template - inline /* auto & */ auto emplace(Args &&... args) - -> decltype(this->construct_alt(access::base::get_alt(*this), - std::forward(args)...)) { - this->destroy(); - auto &result = this->construct_alt(access::base::get_alt(*this), - std::forward(args)...); - this->index_ = I; - return result; - } +template +class assignment : public copy_constructor +{ + using super = copy_constructor; - protected: - template - struct assigner { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { - self->assign_alt(this_alt, std::forward(that_alt).value); - } - assignment *self; - }; +public: + using super::super; + using super::operator=; + + template + inline /* auto & */ auto emplace(Args &&... args) + -> decltype(this->construct_alt(access::base::get_alt(*this), std::forward(args)...)) + { + this->destroy(); + auto &result = + this->construct_alt(access::base::get_alt(*this), std::forward(args)...); + this->index_ = I; + return result; + } + +protected: + template + struct assigner + { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const + { + self->assign_alt(this_alt, std::forward(that_alt).value); + } + assignment *self; + }; - template - inline void assign_alt(alt &a, Arg &&arg) { - if (this->index() == I) { + template + inline void assign_alt(alt &a, Arg &&arg) + { + if (this->index() == I) + { #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) +# pragma warning(push) +# pragma warning(disable : 4244) #endif - a.value = std::forward(arg); + a.value = std::forward(arg); #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif - } else { - struct { - void operator()(std::true_type) const { - this_->emplace(std::forward(arg_)); - } - void operator()(std::false_type) const { - this_->emplace(T(std::forward(arg_))); - } - assignment *this_; - Arg &&arg_; - } impl{this, std::forward(arg)}; - impl(bool_constant < std::is_nothrow_constructible::value || - !std::is_nothrow_move_constructible::value > {}); - } - } + } + else + { + struct + { + void operator()(std::true_type) const { this_->emplace(std::forward(arg_)); } + void operator()(std::false_type) const { this_->emplace(T(std::forward(arg_))); } + assignment *this_; + Arg &&arg_; + } impl{this, std::forward(arg)}; + impl(bool_constant < std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value > {}); + } + } + + template + inline void generic_assign(That &&that) + { + if (this->valueless_by_exception() && that.valueless_by_exception()) + { + // do nothing. + } + else if (that.valueless_by_exception()) + { + this->destroy(); + } + else + { + visitation::alt::visit_alt_at(that.index(), assigner{this}, *this, + std::forward(that)); + } + } +}; + +template +class move_assignment; + +#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ + template \ + class move_assignment, move_assignable_trait> : public assignment> \ + { \ + using super = assignment>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + move_assignment(const move_assignment &) = default; \ + move_assignment(move_assignment &&) = default; \ + ~move_assignment() = default; \ + move_assignment &operator=(const move_assignment &) = default; \ + definition \ + } + +MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, + move_assignment &operator=(move_assignment &&that) = default;); + +MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Available, + move_assignment & + operator=(move_assignment &&that) noexcept( + all<(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value)...>::value) { + this->generic_assign(std::move(that)); + return *this; + }); + +MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, + move_assignment &operator=(move_assignment &&) = delete;); + +#undef MPARK_VARIANT_MOVE_ASSIGNMENT + +template +class copy_assignment; + +#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ + template \ + class copy_assignment, copy_assignable_trait> \ + : public move_assignment> \ + { \ + using super = move_assignment>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + copy_assignment(const copy_assignment &) = default; \ + copy_assignment(copy_assignment &&) = default; \ + ~copy_assignment() = default; \ + definition copy_assignment &operator=(copy_assignment &&) = default; \ + } + +MPARK_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable, + copy_assignment &operator=(const copy_assignment &that) = default;); + +MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Available, + copy_assignment & + operator=(const copy_assignment &that) { + this->generic_assign(that); + return *this; + }); + +MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable, + copy_assignment &operator=(const copy_assignment &) = delete;); + +#undef MPARK_VARIANT_COPY_ASSIGNMENT +template +class impl : public copy_assignment> +{ + using super = copy_assignment>; + +public: + using super::super; + using super::operator=; + + impl(const impl &) = default; + impl(impl &&) = default; + ~impl() = default; + impl &operator=(const impl &) = default; + impl &operator=(impl &&) = default; - template - inline void generic_assign(That &&that) { - if (this->valueless_by_exception() && that.valueless_by_exception()) { - // do nothing. - } else if (that.valueless_by_exception()) { - this->destroy(); - } else { - visitation::alt::visit_alt_at( - that.index(), - assigner{this} - , - *this, - std::forward(that)); + template + inline void assign(Arg &&arg) + { + this->assign_alt(access::base::get_alt(*this), std::forward(arg)); + } + + inline void swap(impl &that) + { + if (this->valueless_by_exception() && that.valueless_by_exception()) + { + // do nothing. + } + else if (this->index() == that.index()) + { + visitation::alt::visit_alt_at(this->index(), swapper{}, *this, that); + } + else + { + impl *lhs = this; + impl *rhs = std::addressof(that); + if (lhs->move_nothrow() && !rhs->move_nothrow()) + { + std::swap(lhs, rhs); + } + impl tmp(std::move(*rhs)); +#ifdef MPARK_EXCEPTIONS + // EXTENSION: When the move construction of `lhs` into `rhs` throws + // and `tmp` is nothrow move constructible then we move `tmp` back + // into `rhs` and provide the strong exception safety guarantee. + try + { + this->generic_construct(*rhs, lib::move(*lhs)); + } + catch (...) + { + if (tmp.move_nothrow()) + { + this->generic_construct(*rhs, lib::move(tmp)); } + throw; } - }; +#else + this->generic_construct(*rhs, std::move(*lhs)); +#endif + this->generic_construct(*lhs, std::move(tmp)); + } + } + +private: + struct swapper + { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const + { + using std::swap; + swap(this_alt.value, that_alt.value); + } + }; + + inline constexpr bool move_nothrow() const + { + return this->valueless_by_exception() || + std::array{ + {std::is_nothrow_move_constructible::value...}}[this->index()]; + } +}; + +template +struct is_non_narrowing_convertible +{ + template + static std::true_type test(T(&&)[1]); + + template + static auto impl(int) -> decltype(test({std::declval()})); + + template + static auto impl(...) -> std::false_type; + + static constexpr bool value = decltype(impl(0))::value; +}; + +template ::value, + typename = void> +struct overload_leaf +{}; + +template +struct overload_leaf +{ + using impl = size_constant (*)(T); + operator impl() const { return nullptr; }; +}; + +template +struct overload_leaf= 5 + , + enable_if_t, bool>::value + ? std::is_same, bool>::value + : is_non_narrowing_convertible::value> +#endif + > +{ + using impl = size_constant (*)(T); + operator impl() const { return nullptr; }; +}; + +template +struct overload_impl +{ +private: + template + struct impl; + + template + struct impl> : overload_leaf... + {}; + +public: + using type = impl>; +}; + +template +using overload = typename overload_impl::type; + +template +using best_match = invoke_result_t, Arg>; + +template +struct is_in_place_index : std::false_type +{}; + +template +struct is_in_place_index> : std::true_type +{}; + +template +struct is_in_place_type : std::false_type +{}; + +template +struct is_in_place_type> : std::true_type +{}; } // namespace detail } // namespace nostd From 67dae8ab3ab71b5f29859c92c162e4dd7d3c4465 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 19:35:48 -0700 Subject: [PATCH 10/42] Fill out variant --- .../nostd/detail/dependent_type.h | 18 ++ api/include/opentelemetry/nostd/type_traits.h | 50 ++++- api/include/opentelemetry/nostd/variant.h | 171 ++++++++++++++++++ 3 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 api/include/opentelemetry/nostd/detail/dependent_type.h diff --git a/api/include/opentelemetry/nostd/detail/dependent_type.h b/api/include/opentelemetry/nostd/detail/dependent_type.h new file mode 100644 index 0000000000..c2b366633f --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/dependent_type.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +template +struct dependent_type : T +{}; +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index f968d68d6f..3324e66676 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "opentelemetry/nostd/detail/void.h" #include "opentelemetry/version.h" @@ -51,5 +51,53 @@ struct remove_all_extents> : remove_all_extents */ template using remove_all_extents_t = typename remove_all_extents::type; + +/** + * Back port of std::is_swappable + */ +namespace detail +{ +namespace swappable +{ + +using std::swap; + +template +struct is_swappable +{ +private: + template (), std::declval()))> + inline static std::true_type test(int); + + template + inline static std::false_type test(...); + +public: + static constexpr bool value = decltype(test(0))::value; +}; + +} // namespace swappable +} // namespace detail + +using detail::swappable::is_swappable; + +/** + * Back port of std::is_swappable + */ +namespace detail { +namespace swappable { +template +struct is_nothrow_swappable +{ + static constexpr bool value = noexcept(swap(std::declval(), std::declval())); +}; + +template +struct is_nothrow_swappable : std::false_type +{}; +} // namespace swappable +} // namespace detail +template +using is_nothrow_swappable = detail::swappable::is_nothrow_swappable::value, T>; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 4653fce0dd..e3de42b4e1 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -12,6 +12,7 @@ #include "opentelemetry/nostd/detail/variant_alternative.h" #include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/nostd/detail/variant_size.h" +#include "opentelemetry/nostd/detail/dependent_type.h" #include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" @@ -832,6 +833,176 @@ struct is_in_place_type> : std::true_type {}; } // namespace detail +template +class variant +{ + static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative."); + + static_assert(detail::all::value...>::value, + "variant can not have an array type as an alternative."); + + static_assert(detail::all::value...>::value, + "variant can not have a reference type as an alternative."); + + static_assert(detail::all::value...>::value, + "variant can not have a void type as an alternative."); + +public: + template , + enable_if_t::value, int> = 0> + inline constexpr variant() noexcept(std::is_nothrow_default_constructible::value) + : impl_(in_place_index_t<0>{}) + {} + + variant(const variant &) = default; + variant(variant &&) = default; + + template , + enable_if_t::value, int> = 0, + enable_if_t::value, int> = 0, + enable_if_t::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = detail::type_pack_element_t, + enable_if_t::value, int> = 0> + inline constexpr variant(Arg &&arg) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, std::forward(arg)) + {} + + template , + enable_if_t::value, int> = 0> + inline explicit constexpr variant(in_place_index_t, Args &&... args) noexcept( + std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, std::forward(args)...) + {} + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = detail::type_pack_element_t, + enable_if_t &, Args...>::value, int> = 0> + inline explicit constexpr variant( + in_place_index_t, + std::initializer_list il, + Args &&... args) noexcept(std::is_nothrow_constructible &, + Args...>::value) + : impl_(in_place_index_t{}, il, std::forward(args)...) + {} + + template ::value, + enable_if_t::value, int> = 0> + inline explicit constexpr variant(in_place_type_t, Args &&... args) noexcept( + std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, std::forward(args)...) + {} + + template ::value, + enable_if_t &, Args...>::value, + int> = 0> + inline explicit constexpr variant( + in_place_type_t, + std::initializer_list il, + Args &&... args) noexcept(std::is_nothrow_constructible &, + Args...>::value) + : impl_(in_place_index_t{}, il, std::forward(args)...) + {} + + ~variant() = default; + + variant &operator=(const variant &) = default; + variant &operator=(variant &&) = default; + + template , variant>::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = detail::type_pack_element_t, + enable_if_t<(std::is_assignable::value && + std::is_constructible::value), + int> = 0> + inline variant &operator=(Arg &&arg) noexcept((std::is_nothrow_assignable::value && + std::is_nothrow_constructible::value)) + { + impl_.template assign(std::forward(arg)); + return *this; + } + + template , + enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) + { + return impl_.template emplace(std::forward(args)...); + } + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = detail::type_pack_element_t, + enable_if_t &, Args...>::value, int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) + { + return impl_.template emplace(il, std::forward(args)...); + } + + template ::value, + enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) + { + return impl_.template emplace(std::forward(args)...); + } + + template ::value, + enable_if_t &, Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) + { + return impl_.template emplace(il, std::forward(args)...); + } + + inline constexpr bool valueless_by_exception() const noexcept + { + return impl_.valueless_by_exception(); + } + + inline constexpr std::size_t index() const noexcept { return impl_.index(); } + + template , Dummy>::value && + detail::dependent_type, Dummy>::value)...>::value, + int> = 0> + inline void swap(variant &that) noexcept( + detail::all<(std::is_nothrow_move_constructible::value && + is_nothrow_swappable::value)...>::value) + { + impl_.swap(that.impl_); + } + +private: + detail::impl impl_; + + friend struct detail::access::variant; + friend struct detail::visitation::variant; +}; + } // namespace nostd OPENTELEMETRY_END_NAMESPACE From ff80f15fb46f2c4098f4dd073c74f85a48c63031 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 20:01:39 -0700 Subject: [PATCH 11/42] Fill out variant --- api/include/opentelemetry/nostd/type_traits.h | 6 + api/include/opentelemetry/nostd/variant.h | 300 ++++++++++++++++-- 2 files changed, 283 insertions(+), 23 deletions(-) diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index 3324e66676..54f2a3948a 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -9,6 +9,12 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { +/** + * Back port of std::add_pointer_t + */ +template< class T > +using add_pointer_t = typename std::add_pointer::type; + /** * Back port of std::enable_if_t */ diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index e3de42b4e1..8e82bf8589 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -5,6 +5,8 @@ #include #include "opentelemetry/nostd/detail/all.h" +#include "opentelemetry/nostd/detail/functional.h" +#include "opentelemetry/nostd/detail/dependent_type.h" #include "opentelemetry/nostd/detail/find_index.h" #include "opentelemetry/nostd/detail/recursive_union.h" #include "opentelemetry/nostd/detail/trait.h" @@ -12,7 +14,6 @@ #include "opentelemetry/nostd/detail/variant_alternative.h" #include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/nostd/detail/variant_size.h" -#include "opentelemetry/nostd/detail/dependent_type.h" #include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" @@ -712,13 +713,13 @@ class impl : public copy_assignment> // into `rhs` and provide the strong exception safety guarantee. try { - this->generic_construct(*rhs, lib::move(*lhs)); + this->generic_construct(*rhs, std::move(*lhs)); } catch (...) { if (tmp.move_nothrow()) { - this->generic_construct(*rhs, lib::move(tmp)); + this->generic_construct(*rhs, std::move(tmp)); } throw; } @@ -858,7 +859,7 @@ class variant variant(variant &&) = default; template , + typename Decayed = decay_t, enable_if_t::value, int> = 0, enable_if_t::value, int> = 0, enable_if_t::value, int> = 0, @@ -902,12 +903,12 @@ class variant : impl_(in_place_index_t{}, std::forward(args)...) {} - template ::value, - enable_if_t &, Args...>::value, - int> = 0> + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + enable_if_t &, Args...>::value, int> = 0> inline explicit constexpr variant( in_place_type_t, std::initializer_list il, @@ -922,13 +923,13 @@ class variant variant &operator=(const variant &) = default; variant &operator=(variant &&) = default; - template , variant>::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = detail::type_pack_element_t, - enable_if_t<(std::is_assignable::value && - std::is_constructible::value), - int> = 0> + template < + typename Arg, + enable_if_t, variant>::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = detail::type_pack_element_t, + enable_if_t<(std::is_assignable::value && std::is_constructible::value), + int> = 0> inline variant &operator=(Arg &&arg) noexcept((std::is_nothrow_assignable::value && std::is_nothrow_constructible::value)) { @@ -965,12 +966,12 @@ class variant return impl_.template emplace(std::forward(args)...); } - template ::value, - enable_if_t &, Args...>::value, - int> = 0> + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + enable_if_t &, Args...>::value, int> = 0> inline T &emplace(std::initializer_list il, Args &&... args) { return impl_.template emplace(il, std::forward(args)...); @@ -1003,6 +1004,259 @@ class variant friend struct detail::visitation::variant; }; +template +inline constexpr bool holds_alternative(const variant &v) noexcept +{ + return v.index() == I; +} + +template +inline constexpr bool holds_alternative(const variant &v) noexcept +{ + return holds_alternative::value>(v); +} + +namespace detail +{ +template +struct generic_get_impl +{ + constexpr generic_get_impl(int) noexcept {} + + constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(access::variant::get_alt(std::forward(v)).value) +}; + +template +inline constexpr AUTO_REFREF generic_get(V &&v) AUTO_REFREF_RETURN(generic_get_impl( + holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))(std::forward(v))) +} // namespace detail + +template +inline constexpr variant_alternative_t> &get(variant &v) +{ + return detail::generic_get(v); +} + +template +inline constexpr variant_alternative_t> &&get(variant &&v) +{ + return detail::generic_get(std::move(v)); +} + +template +inline constexpr const variant_alternative_t> &get(const variant &v) +{ + return detail::generic_get(v); +} + +template +inline constexpr const variant_alternative_t> &&get(const variant &&v) +{ + return detail::generic_get(std::move(v)); +} + +template +inline constexpr T &get(variant &v) +{ + return get::value>(v); +} + +template +inline constexpr T &&get(variant &&v) +{ + return get::value>(std::move(v)); +} + +template +inline constexpr const T &get(const variant &v) +{ + return get::value>(v); +} + +template +inline constexpr const T &&get(const variant &&v) +{ + return get::value>(std::move(v)); +} + +namespace detail +{ + +template +inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept AUTO_RETURN( + v &&holds_alternative(*v) ? std::addressof(access::variant::get_alt(*v).value) : nullptr) + +} // namespace detail + +template +inline constexpr add_pointer_t>> get_if( + variant *v) noexcept +{ + return detail::generic_get_if(v); +} + +template +inline constexpr add_pointer_t>> get_if( + const variant *v) noexcept +{ + return detail::generic_get_if(v); +} + +template +inline constexpr add_pointer_t get_if(variant *v) noexcept +{ + return get_if::value>(v); +} + +template +inline constexpr add_pointer_t get_if(const variant *v) noexcept +{ + return get_if::value>(v); +} + +namespace detail +{ +template +struct convert_to_bool +{ + template + inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const + { + static_assert(std::is_convertible, bool>::value, + "relational operators must return a type" + " implicitly convertible to bool"); + return invoke(RelOp{}, std::forward(lhs), std::forward(rhs)); + } +}; +} // namespace detail + +template +inline constexpr bool operator==(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using equal_to = detail::convert_to_bool; + return lhs.index() == rhs.index() && (lhs.valueless_by_exception() || + variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); +} + +template +inline constexpr bool operator!=(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using not_equal_to = detail::convert_to_bool; + return lhs.index() != rhs.index() || + (!lhs.valueless_by_exception() && + variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); +} + +template +inline constexpr bool operator<(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using less = detail::convert_to_bool; + return !rhs.valueless_by_exception() && + (lhs.valueless_by_exception() || lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); +} + +template +inline constexpr bool operator>(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using greater = detail::convert_to_bool; + return !lhs.valueless_by_exception() && + (rhs.valueless_by_exception() || lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); +} + +template +inline constexpr bool operator<=(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using less_equal = detail::convert_to_bool; + return lhs.valueless_by_exception() || + (!rhs.valueless_by_exception() && + (lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); +} + +template +inline constexpr bool operator>=(const variant &lhs, const variant &rhs) +{ + using detail::visitation::variant; + using greater_equal = detail::convert_to_bool; + return rhs.valueless_by_exception() || + (!lhs.valueless_by_exception() && + (lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs)))); +} + +struct monostate +{}; + +inline constexpr bool operator<(monostate, monostate) noexcept +{ + return false; +} + +inline constexpr bool operator>(monostate, monostate) noexcept +{ + return false; +} + +inline constexpr bool operator<=(monostate, monostate) noexcept +{ + return true; +} + +inline constexpr bool operator>=(monostate, monostate) noexcept +{ + return true; +} + +inline constexpr bool operator==(monostate, monostate) noexcept +{ + return true; +} + +inline constexpr bool operator!=(monostate, monostate) noexcept +{ + return false; +} + +namespace detail +{ + +template +inline constexpr bool all_of_impl(const std::array &bs, std::size_t idx) +{ + return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); +} + +template +inline constexpr bool all_of(const std::array &bs) +{ + return all_impl(bs, 0); +} + +} // namespace detail + +template +inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( + (detail::all_of(std::array{{!vs.valueless_by_exception()...}}) + ? (void)0 + : throw_bad_variant_access()), + detail::visitation::variant::visit_value(std::forward(visitor), + std::forward(vs)...)) template +inline auto swap(variant &lhs, variant &rhs) noexcept(noexcept(lhs.swap(rhs))) + -> decltype(lhs.swap(rhs)) +{ + lhs.swap(rhs); +} } // namespace nostd OPENTELEMETRY_END_NAMESPACE From b25271c2f5d089438c665fa24f68d92f38f8eba9 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 22:26:52 -0700 Subject: [PATCH 12/42] Add variant test --- .../opentelemetry/nostd/detail/functional.h | 60 +++++++++++++++++++ .../opentelemetry/nostd/detail/invoke.h | 4 +- api/include/opentelemetry/nostd/type_traits.h | 2 +- api/test/nostd/variant_test.cc | 31 +++++++--- 4 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 api/include/opentelemetry/nostd/detail/functional.h diff --git a/api/include/opentelemetry/nostd/detail/functional.h b/api/include/opentelemetry/nostd/detail/functional.h new file mode 100644 index 0000000000..a426e5358d --- /dev/null +++ b/api/include/opentelemetry/nostd/detail/functional.h @@ -0,0 +1,60 @@ +#pragma once + +#include + +#include "opentelemetry/version.h" + +#define MPARK_RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +namespace detail +{ +struct equal_to +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) == std::forward(rhs)) +}; + +struct not_equal_to +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) != std::forward(rhs)) +}; + +struct less +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) < std::forward(rhs)) +}; + +struct greater +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) > std::forward(rhs)) +}; + +struct less_equal +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) <= std::forward(rhs)) +}; + +struct greater_equal +{ + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + MPARK_RETURN(std::forward(lhs) >= std::forward(rhs)) +}; +} // namespace detail +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE + +#undef MPARK_RETURN diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h index c744e2e238..b01aa00d78 100644 --- a/api/include/opentelemetry/nostd/detail/invoke.h +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -107,11 +107,11 @@ namespace detail {}; template - struct invoke_result(), std::declval()...))>, + struct invoke_result(), std::declval()...))>, F, Args...> { - using type = decltype(invoke(std::declval(), std::declval()...)); + using type = decltype(nostd::invoke(std::declval(), std::declval()...)); }; } // namespace detail diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index 54f2a3948a..d19f5db132 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -19,7 +19,7 @@ using add_pointer_t = typename std::add_pointer::type; * Back port of std::enable_if_t */ template -using enable_if_t = typename std::enable_if::value; +using enable_if_t = typename std::enable_if::type; /** * Back port of std::remove_const_t diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 37f88d3cfd..91cbb6f63b 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -4,9 +4,10 @@ #include -using opentelemetry::nostd::variant; -using opentelemetry::nostd::variant_alternative_t; -using opentelemetry::nostd::variant_size; +namespace nostd = opentelemetry::nostd; +/* using opentelemetry::nostd::variant; */ +/* using opentelemetry::nostd::variant_alternative_t; */ +/* using opentelemetry::nostd::variant_size; */ TEST(TypePackElementTest, IndexedType) { @@ -18,15 +19,27 @@ TEST(TypePackElementTest, IndexedType) TEST(VariantSizeTest, GetVariantSize) { - EXPECT_EQ(variant_size>::value, 0); - EXPECT_EQ(variant_size>::value, 1); - EXPECT_EQ((variant_size>::value), 2); + EXPECT_EQ(nostd::variant_size>::value, 0); + EXPECT_EQ(nostd::variant_size>::value, 1); + EXPECT_EQ((nostd::variant_size>::value), 2); } TEST(VariantAlternativeTest, GetVariantSize) { - EXPECT_TRUE((std::is_same>, int>::value)); - EXPECT_TRUE((std::is_same>, double>::value)); + EXPECT_TRUE((std::is_same>, int>::value)); + EXPECT_TRUE((std::is_same>, double>::value)); EXPECT_TRUE( - (std::is_same>, const double>::value)); + (std::is_same>, const double>::value)); +} + +struct A { + int operator()(int) { return 1;} + + char operator()(char) { return 'a';} +}; + +TEST(VariantTest, Get) { + nostd::variant v, w; + v = 12; + EXPECT_EQ(nostd::get(v), 12); } From 5cfe001288cca5e9188977ff02e02247019eea44 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Thu, 2 Apr 2020 22:45:41 -0700 Subject: [PATCH 13/42] Add get tests --- api/include/opentelemetry/nostd/variant.h | 2 +- api/test/nostd/variant_test.cc | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 8e82bf8589..9044ed8c15 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -707,7 +707,7 @@ class impl : public copy_assignment> std::swap(lhs, rhs); } impl tmp(std::move(*rhs)); -#ifdef MPARK_EXCEPTIONS +#if __EXCEPTIONS // EXTENSION: When the move construction of `lhs` into `rhs` throws // and `tmp` is nothrow move constructible then we move `tmp` back // into `rhs` and provide the strong exception safety guarantee. diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 91cbb6f63b..919413edb4 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -32,14 +32,24 @@ TEST(VariantAlternativeTest, GetVariantSize) (std::is_same>, const double>::value)); } -struct A { - int operator()(int) { return 1;} - - char operator()(char) { return 'a';} -}; - TEST(VariantTest, Get) { nostd::variant v, w; v = 12; EXPECT_EQ(nostd::get(v), 12); + EXPECT_EQ(nostd::get<0>(v), 12); + w = v; + EXPECT_EQ(nostd::get(w), 12); + EXPECT_EQ(*nostd::get_if(&v), 12); + EXPECT_EQ(nostd::get_if(&v), nullptr); +#if __EXCEPTIONS + EXPECT_THROW(nostd::get(w), nostd::bad_variant_access); +#else + EXPECT_DEATH({ nostd::get(w); }, ""); +#endif +} + +TEST(VariantTest, Comparison) { + nostd::variant v, w; + v = 3.0f; + /* EXPECT_TRUE(v == w); */ } From 9399c02f6591fc452d55aaafef4a6586e969c271 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 00:52:44 -0700 Subject: [PATCH 14/42] Add visit test --- api/include/opentelemetry/nostd/detail/invoke.h | 6 +++--- api/include/opentelemetry/nostd/variant.h | 6 +++--- api/test/nostd/variant_test.cc | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h index b01aa00d78..7e7be3c3b7 100644 --- a/api/include/opentelemetry/nostd/detail/invoke.h +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -76,7 +76,7 @@ struct Invoke }; template -inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) +inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args) MPARK_RETURN(Invoke::value, (std::is_base_of>::value ? 0 @@ -88,7 +88,7 @@ inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) # pragma warning(disable : 4100) #endif template - inline constexpr auto invoke(F &&f, Args &&... args) + inline constexpr auto invoke_impl(F &&f, Args &&... args) MPARK_RETURN(std::forward(f)(std::forward(args)...)) #ifdef _MSC_VER # pragma warning(pop) @@ -97,7 +97,7 @@ inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) template inline constexpr auto invoke(F &&f, Args &&... args) - MPARK_RETURN(detail::invoke(std::forward(f), std::forward(args)...)); + MPARK_RETURN(detail::invoke_impl(std::forward(f), std::forward(args)...)); namespace detail { diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 9044ed8c15..85cf884fe1 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -244,7 +244,7 @@ struct variant template inline static constexpr bool does_not_handle() { - return is_invocable::value; + return nostd::is_invocable::value; } }; @@ -1234,13 +1234,13 @@ namespace detail template inline constexpr bool all_of_impl(const std::array &bs, std::size_t idx) { - return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); + return idx >= N || (bs[idx] && all_of_impl(bs, idx + 1)); } template inline constexpr bool all_of(const std::array &bs) { - return all_impl(bs, 0); + return all_of_impl(bs, 0); } } // namespace detail diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 919413edb4..2e19e6932f 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -50,6 +50,20 @@ TEST(VariantTest, Get) { TEST(VariantTest, Comparison) { nostd::variant v, w; + EXPECT_TRUE(v == w); + EXPECT_FALSE(v != w); v = 3.0f; - /* EXPECT_TRUE(v == w); */ + EXPECT_TRUE(v != w); + EXPECT_FALSE(v == w); +} + +TEST(VariantTest, Visit) { + nostd::variant v; + struct { + int operator()(int) { return 0; } + int operator()(float) { return 1; } + } a; + EXPECT_EQ(nostd::visit(a, v), 0); + v = 2.0f; + EXPECT_EQ(nostd::visit(a, v), 1); } From 1b605b13744a869ef75983ed5adee0307c30b1fb Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 01:11:32 -0700 Subject: [PATCH 15/42] Add more tests --- api/test/nostd/variant_test.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 2e19e6932f..e0c4e481e8 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -1,13 +1,21 @@ #include "opentelemetry/nostd/variant.h" #include +#include #include namespace nostd = opentelemetry::nostd; -/* using opentelemetry::nostd::variant; */ -/* using opentelemetry::nostd::variant_alternative_t; */ -/* using opentelemetry::nostd::variant_size; */ + +class DestroyCounter +{ +public: + explicit DestroyCounter(int *count) : count_{count} {} + ~DestroyCounter() { ++*count_; } + +private: + int *count_; +}; TEST(TypePackElementTest, IndexedType) { @@ -67,3 +75,12 @@ TEST(VariantTest, Visit) { v = 2.0f; EXPECT_EQ(nostd::visit(a, v), 1); } + +TEST(VariantTest, Destructor) { + nostd::variant v; + int destroy_count = 0; + v = DestroyCounter{&destroy_count}; + destroy_count = 0; + v = 1; + EXPECT_EQ(destroy_count, 1); +} From 0462eea5d87736e19560a6f4ba44e57a7d565010 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 11:34:35 -0700 Subject: [PATCH 16/42] Fix variant tests --- api/include/opentelemetry/nostd/in_place.hpp | 35 - api/include/opentelemetry/nostd/lib.hpp | 503 ------ api/include/opentelemetry/nostd/variant.h | 10 +- api/include/opentelemetry/nostd/variant.hpp | 1610 ------------------ 4 files changed, 5 insertions(+), 2153 deletions(-) delete mode 100644 api/include/opentelemetry/nostd/in_place.hpp delete mode 100644 api/include/opentelemetry/nostd/lib.hpp delete mode 100644 api/include/opentelemetry/nostd/variant.hpp diff --git a/api/include/opentelemetry/nostd/in_place.hpp b/api/include/opentelemetry/nostd/in_place.hpp deleted file mode 100644 index 56cae13113..0000000000 --- a/api/include/opentelemetry/nostd/in_place.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#ifndef MPARK_IN_PLACE_HPP -#define MPARK_IN_PLACE_HPP - -#include - -#include "config.hpp" - -namespace mpark { - - struct in_place_t { explicit in_place_t() = default; }; - - template - struct in_place_index_t { explicit in_place_index_t() = default; }; - - template - struct in_place_type_t { explicit in_place_type_t() = default; }; - -#ifdef MPARK_VARIABLE_TEMPLATES - constexpr in_place_t in_place{}; - - template constexpr in_place_index_t in_place_index{}; - - template constexpr in_place_type_t in_place_type{}; -#endif - -} // namespace mpark - -#endif // MPARK_IN_PLACE_HPP diff --git a/api/include/opentelemetry/nostd/lib.hpp b/api/include/opentelemetry/nostd/lib.hpp deleted file mode 100644 index 7ba94d6a73..0000000000 --- a/api/include/opentelemetry/nostd/lib.hpp +++ /dev/null @@ -1,503 +0,0 @@ -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#ifndef MPARK_LIB_HPP -#define MPARK_LIB_HPP - -#include -#include -#include -#include - -#include "config.hpp" - -#define MPARK_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } - -namespace mpark { - namespace lib { - template - struct identity { using type = T; }; - - inline namespace cpp14 { - template - struct array { - constexpr const T &operator[](std::size_t index) const { - return data[index]; - } - - T data[N == 0 ? 1 : N]; - }; - - template - using add_pointer_t = typename std::add_pointer::type; - - template - using common_type_t = typename std::common_type::type; - - template - using decay_t = typename std::decay::type; - - template - using enable_if_t = typename std::enable_if::type; - - template - using remove_const_t = typename std::remove_const::type; - - template - using remove_reference_t = typename std::remove_reference::type; - - template - using remove_cvref_t = - typename std::remove_cv>::type; - - template - inline constexpr T &&forward(remove_reference_t &t) noexcept { - return static_cast(t); - } - - template - inline constexpr T &&forward(remove_reference_t &&t) noexcept { - static_assert(!std::is_lvalue_reference::value, - "can not forward an rvalue as an lvalue"); - return static_cast(t); - } - - template - inline constexpr remove_reference_t &&move(T &&t) noexcept { - return static_cast &&>(t); - } - -#ifdef MPARK_INTEGER_SEQUENCE - using std::integer_sequence; - using std::index_sequence; - using std::make_index_sequence; - using std::index_sequence_for; -#else - template - struct integer_sequence { - using value_type = T; - static constexpr std::size_t size() noexcept { return sizeof...(Is); } - }; - - template - using index_sequence = integer_sequence; - - template - struct make_index_sequence_concat; - - template - struct make_index_sequence_concat, - index_sequence> - : identity> {}; - - template - struct make_index_sequence_impl; - - template - using make_index_sequence = typename make_index_sequence_impl::type; - - template - struct make_index_sequence_impl - : make_index_sequence_concat, - make_index_sequence> {}; - - template <> - struct make_index_sequence_impl<0> : identity> {}; - - template <> - struct make_index_sequence_impl<1> : identity> {}; - - template - using index_sequence_for = make_index_sequence; -#endif - - // -#ifdef MPARK_TRANSPARENT_OPERATORS - using equal_to = std::equal_to<>; -#else - struct equal_to { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) == lib::forward(rhs)) - }; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS - using not_equal_to = std::not_equal_to<>; -#else - struct not_equal_to { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) != lib::forward(rhs)) - }; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS - using less = std::less<>; -#else - struct less { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) < lib::forward(rhs)) - }; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS - using greater = std::greater<>; -#else - struct greater { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) > lib::forward(rhs)) - }; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS - using less_equal = std::less_equal<>; -#else - struct less_equal { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) <= lib::forward(rhs)) - }; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS - using greater_equal = std::greater_equal<>; -#else - struct greater_equal { - template - inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(lib::forward(lhs) >= lib::forward(rhs)) - }; -#endif - } // namespace cpp14 - - inline namespace cpp17 { - - // - template - using bool_constant = std::integral_constant; - - template - struct voider : identity {}; - - template - using void_t = typename voider::type; - - namespace detail { - namespace swappable { - - using std::swap; - - template - struct is_swappable { - private: - template (), - std::declval()))> - inline static std::true_type test(int); - - template - inline static std::false_type test(...); - - public: - static constexpr bool value = decltype(test(0))::value; - }; - - template - struct is_nothrow_swappable { - static constexpr bool value = - noexcept(swap(std::declval(), std::declval())); - }; - - template - struct is_nothrow_swappable : std::false_type {}; - - } // namespace swappable - } // namespace detail - - using detail::swappable::is_swappable; - - template - using is_nothrow_swappable = - detail::swappable::is_nothrow_swappable::value, T>; - - // - namespace detail { - - template - struct is_reference_wrapper : std::false_type {}; - - template - struct is_reference_wrapper> - : std::true_type {}; - - template - struct Invoke; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN((lib::forward(arg).*pmf)(lib::forward(args)...)) - }; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN((lib::forward(arg).get().*pmf)(lib::forward(args)...)) - }; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN(((*lib::forward(arg)).*pmf)(lib::forward(args)...)) - }; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(lib::forward(arg).*pmo) - }; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(lib::forward(arg).get().*pmo) - }; - - template <> - struct Invoke { - template - inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN((*lib::forward(arg)).*pmo) - }; - - template - inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args) - MPARK_RETURN( - Invoke::value, - (std::is_base_of>::value - ? 0 - : is_reference_wrapper>::value - ? 1 - : 2)>::invoke(f, - lib::forward(arg), - lib::forward(args)...)) - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif - template - inline constexpr auto invoke(F &&f, Args &&... args) - MPARK_RETURN(lib::forward(f)(lib::forward(args)...)) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - } // namespace detail - - template - inline constexpr auto invoke(F &&f, Args &&... args) - MPARK_RETURN(detail::invoke(lib::forward(f), - lib::forward(args)...)) - - namespace detail { - - template - struct invoke_result {}; - - template - struct invoke_result(), std::declval()...))>, - F, - Args...> - : identity(), std::declval()...))> {}; - - } // namespace detail - - template - using invoke_result = detail::invoke_result; - - template - using invoke_result_t = typename invoke_result::type; - - namespace detail { - - template - struct is_invocable : std::false_type {}; - - template - struct is_invocable>, F, Args...> - : std::true_type {}; - - template - struct is_invocable_r : std::false_type {}; - - template - struct is_invocable_r>, - R, - F, - Args...> - : std::is_convertible, R> {}; - - } // namespace detail - - template - using is_invocable = detail::is_invocable; - - template - using is_invocable_r = detail::is_invocable_r; - - // -#ifdef MPARK_BUILTIN_ADDRESSOF - template - inline constexpr T *addressof(T &arg) noexcept { - return __builtin_addressof(arg); - } -#else - namespace detail { - - namespace has_addressof_impl { - - struct fail; - - template - inline fail operator&(T &&); - - template - inline static constexpr bool impl() { - return (std::is_class::value || std::is_union::value) && - !std::is_same()), fail>::value; - } - - } // namespace has_addressof_impl - - template - using has_addressof = bool_constant()>; - - template - inline constexpr T *addressof(T &arg, std::true_type) noexcept { - return std::addressof(arg); - } - - template - inline constexpr T *addressof(T &arg, std::false_type) noexcept { - return &arg; - } - - } // namespace detail - - template - inline constexpr T *addressof(T &arg) noexcept { - return detail::addressof(arg, detail::has_addressof{}); - } -#endif - - template - inline constexpr T *addressof(const T &&) = delete; - - } // namespace cpp17 - - template - struct remove_all_extents : identity {}; - - template - struct remove_all_extents> : remove_all_extents {}; - - template - using remove_all_extents_t = typename remove_all_extents::type; - - template - using size_constant = std::integral_constant; - - template - struct indexed_type : size_constant { using type = T; }; - - template - using all = std::is_same, - integer_sequence>; - -#ifdef MPARK_TYPE_PACK_ELEMENT - template - using type_pack_element_t = __type_pack_element; -#else - template - struct type_pack_element_impl { - private: - template - struct set; - - template - struct set> : indexed_type... {}; - - template - inline static std::enable_if impl(indexed_type); - - inline static std::enable_if impl(...); - - public: - using type = decltype(impl(set>{})); - }; - - template - using type_pack_element = typename type_pack_element_impl::type; - - template - using type_pack_element_t = typename type_pack_element::type; -#endif - -#ifdef MPARK_TRIVIALITY_TYPE_TRAITS - using std::is_trivially_copy_constructible; - using std::is_trivially_move_constructible; - using std::is_trivially_copy_assignable; - using std::is_trivially_move_assignable; -#else - template - struct is_trivially_copy_constructible - : bool_constant< - std::is_copy_constructible::value && __has_trivial_copy(T)> {}; - - template - struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; - - template - struct is_trivially_copy_assignable - : bool_constant< - std::is_copy_assignable::value && __has_trivial_assign(T)> {}; - - template - struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; -#endif - - template - struct dependent_type : T {}; - - template - struct push_back; - - template - using push_back_t = typename push_back::type; - - template - struct push_back, J> { - using type = index_sequence; - }; - - } // namespace lib -} // namespace mpark - -#undef MPARK_RETURN - -#endif // MPARK_LIB_HPP diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 85cf884fe1..989eb13446 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -87,7 +87,7 @@ struct base { template using dispatch_result_t = - decltype(invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); + decltype(nostd::invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); template struct expected @@ -107,7 +107,7 @@ struct base template inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Alts &&... alts) - DECLTYPE_AUTO_RETURN(invoke(std::forward(visitor), std::forward(alts)...)) + DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), std::forward(alts)...)) }; template @@ -139,7 +139,7 @@ struct base { using Expected = dispatch_result_t; using Actual = - decltype(invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + decltype(nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -174,7 +174,7 @@ struct base { using Expected = dispatch_result_t; using Actual = - decltype(invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + decltype(nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -255,7 +255,7 @@ struct variant "`visit` requires the visitor to be exhaustive."); inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) - DECLTYPE_AUTO_RETURN(invoke(std::forward(visitor), + DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), std::forward(values)...)) }; diff --git a/api/include/opentelemetry/nostd/variant.hpp b/api/include/opentelemetry/nostd/variant.hpp deleted file mode 100644 index 423a789bf8..0000000000 --- a/api/include/opentelemetry/nostd/variant.hpp +++ /dev/null @@ -1,1610 +0,0 @@ -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/version.h" - -#include "config.hpp" -#include "in_place.hpp" -#include "lib.hpp" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace nostd -{ - -#define AUTO auto -#define AUTO_RETURN(...) \ - -> lib::decay_t { return __VA_ARGS__; } - -#define AUTO_REFREF auto -#define AUTO_REFREF_RETURN(...) \ - -> decltype((__VA_ARGS__)) { \ - static_assert(std::is_reference::value, ""); \ - return __VA_ARGS__; \ - } - -#define DECLTYPE_AUTO auto -#define DECLTYPE_AUTO_RETURN(...) \ - -> decltype(__VA_ARGS__) { return __VA_ARGS__; } - - class bad_variant_access : public std::exception { - public: - virtual const char *what() const noexcept override { return "bad_variant_access"; } - }; - - [[noreturn]] inline void throw_bad_variant_access() { -#ifdef MPARK_EXCEPTIONS - throw bad_variant_access{}; -#else - std::terminate(); - MPARK_BUILTIN_UNREACHABLE; -#endif - } - - template - class variant; - - template - struct variant_size; - - template - struct variant_size : variant_size {}; - - template - struct variant_size : variant_size {}; - - template - struct variant_size : variant_size {}; - - template - struct variant_size> : lib::size_constant {}; - - template - struct variant_alternative; - - template - using variant_alternative_t = typename variant_alternative::type; - - template - struct variant_alternative - : std::add_const> {}; - - template - struct variant_alternative - : std::add_volatile> {}; - - template - struct variant_alternative - : std::add_cv> {}; - - template - struct variant_alternative> { - static_assert(I < sizeof...(Ts), - "index out of bounds in `std::variant_alternative<>`"); - using type = lib::type_pack_element_t; - }; - - constexpr std::size_t variant_npos = static_cast(-1); - - namespace detail { - - constexpr std::size_t not_found = static_cast(-1); - constexpr std::size_t ambiguous = static_cast(-2); - - inline constexpr std::size_t find_index_impl(std::size_t result, - std::size_t) { - return result; - } - - template - inline constexpr std::size_t find_index_impl(std::size_t result, - std::size_t idx, - bool b, - Bs... bs) { - return b ? (result != not_found ? ambiguous - : find_index_impl(idx, idx + 1, bs...)) - : find_index_impl(result, idx + 1, bs...); - } - - template - inline constexpr std::size_t find_index() { - return find_index_impl(not_found, 0, std::is_same::value...); - } - - template - using find_index_sfinae_impl = - lib::enable_if_t>; - - template - using find_index_sfinae = find_index_sfinae_impl()>; - - template - struct find_index_checked_impl : lib::size_constant { - static_assert(I != not_found, "the specified type is not found."); - static_assert(I != ambiguous, "the specified type is ambiguous."); - }; - - template - using find_index_checked = find_index_checked_impl()>; - - struct valueless_t {}; - - enum class Trait { TriviallyAvailable, Available, Unavailable }; - - template class IsTriviallyAvailable, - template class IsAvailable> - inline constexpr Trait trait() { - return IsTriviallyAvailable::value - ? Trait::TriviallyAvailable - : IsAvailable::value ? Trait::Available - : Trait::Unavailable; - } - - inline constexpr Trait common_trait_impl(Trait result) { return result; } - - template - inline constexpr Trait common_trait_impl(Trait result, - Trait t, - Traits... ts) { - return static_cast(t) > static_cast(result) - ? common_trait_impl(t, ts...) - : common_trait_impl(result, ts...); - } - - template - inline constexpr Trait common_trait(Traits... ts) { - return common_trait_impl(Trait::TriviallyAvailable, ts...); - } - - template - struct traits { - static constexpr Trait copy_constructible_trait = - common_trait(trait()...); - - static constexpr Trait move_constructible_trait = - common_trait(trait()...); - - static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, - trait()...); - - static constexpr Trait move_assignable_trait = - common_trait(move_constructible_trait, - trait()...); - - static constexpr Trait destructible_trait = - common_trait(trait()...); - }; - - namespace access { - - struct recursive_union { - template - struct get_alt_impl { - template - inline constexpr AUTO_REFREF operator()(V &&v) const - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) - }; - - template - struct get_alt_impl<0, Dummy> { - template - inline constexpr AUTO_REFREF operator()(V &&v) const - AUTO_REFREF_RETURN(lib::forward(v).head_) - }; - - template - inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) - }; - - struct base { - template - inline static constexpr AUTO_REFREF get_alt(V &&v) -#ifdef _MSC_VER - AUTO_REFREF_RETURN(recursive_union::get_alt( - lib::forward(v).data_, in_place_index_t{})) -#else - AUTO_REFREF_RETURN(recursive_union::get_alt( - data(lib::forward(v)), in_place_index_t{})) -#endif - }; - - struct variant { - template - inline static constexpr AUTO_REFREF get_alt(V &&v) - AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) - }; - - } // namespace access - - namespace visitation { - - struct base { - template - using dispatch_result_t = decltype( - lib::invoke(std::declval(), - access::base::get_alt<0>(std::declval())...)); - - template - struct expected { - template - inline static constexpr bool but_got() { - return std::is_same::value; - } - }; - - template - struct visit_return_type_check { - static_assert( - expected::template but_got(), - "`visit` requires the visitor to have a single return type"); - - template - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, - Alts &&... alts) - DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), - lib::forward(alts)...)) - }; - - template - inline static constexpr const T &at(const T &elem) noexcept { - return elem; - } - - template - inline static constexpr const lib::remove_all_extents_t &at( - const lib::array &elems, std::size_t i, Is... is) noexcept { - return at(elems[i], is...); - } - - template - inline static constexpr lib::array, sizeof...(Fs) + 1> - make_farray(F &&f, Fs &&... fs) { - return {{lib::forward(f), lib::forward(fs)...}}; - } - - template - struct make_fmatrix_impl { - - template - inline static constexpr dispatch_result_t dispatch( - F &&f, Vs &&... vs) { - using Expected = dispatch_result_t; - using Actual = decltype(lib::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...)); - return visit_return_type_check::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...); - } - - template - struct impl; - - template - struct impl> { - inline constexpr AUTO operator()() const - AUTO_RETURN(&dispatch) - }; - - template - struct impl, Ls...> { - inline constexpr AUTO operator()() const - AUTO_RETURN( - make_farray(impl, Ls...>{}()...)) - }; - }; - - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN( - typename make_fmatrix_impl::template impl< - lib::index_sequence<>, - lib::make_index_sequence::size()>...>{}()) - - template - struct make_fdiagonal_impl { - template - inline static constexpr dispatch_result_t dispatch( - F &&f, Vs &&... vs) { - using Expected = dispatch_result_t; - using Actual = decltype( - lib::invoke(lib::forward(f), - access::base::get_alt(lib::forward(vs))...)); - return visit_return_type_check::invoke( - lib::forward(f), - access::base::get_alt(lib::forward(vs))...); - } - - template - inline static constexpr AUTO impl(lib::index_sequence) - AUTO_RETURN(make_farray(&dispatch...)) - }; - - template - inline static constexpr auto make_fdiagonal() - -> decltype(make_fdiagonal_impl::impl( - lib::make_index_sequence::size()>{})) { - static_assert(lib::all<(lib::decay_t::size() == - lib::decay_t::size())...>::value, - "all of the variants must be the same size."); - return make_fdiagonal_impl::impl( - lib::make_index_sequence::size()>{}); - } - }; - -#if !defined(MPARK_VARIANT_SWITCH_VISIT) && \ - (!defined(_MSC_VER) || _MSC_VER >= 1910) - template - using fmatrix_t = decltype(base::make_fmatrix()); - - template - struct fmatrix { - static constexpr fmatrix_t value = - base::make_fmatrix(); - }; - - template - constexpr fmatrix_t fmatrix::value; - - template - using fdiagonal_t = decltype(base::make_fdiagonal()); - - template - struct fdiagonal { - static constexpr fdiagonal_t value = - base::make_fdiagonal(); - }; - - template - constexpr fdiagonal_t fdiagonal::value; -#endif - - struct alt { - template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN(base::at( - base::make_fmatrix(vs)))...>(), - vs.index()...)(lib::forward(visitor), - as_base(lib::forward(vs))...)) - - template - inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, - Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN(base::at( - base::make_fdiagonal(vs)))...>(), - index)(lib::forward(visitor), - as_base(lib::forward(vs))...)) - }; - - struct variant { - private: - template - struct visitor { - template - inline static constexpr bool does_not_handle() { - return lib::is_invocable::value; - } - }; - - template - struct visit_exhaustiveness_check { - static_assert(visitor::template does_not_handle(), - "`visit` requires the visitor to be exhaustive."); - - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, - Values &&... values) - DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), - lib::forward(values)...)) - }; - - template - struct value_visitor { - Visitor &&visitor_; - - template - inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const - DECLTYPE_AUTO_RETURN( - visit_exhaustiveness_check< - Visitor, - decltype((lib::forward(alts).value))...>:: - invoke(lib::forward(visitor_), - lib::forward(alts).value...)) - }; - - template - inline static constexpr AUTO make_value_visitor(Visitor &&visitor) - AUTO_RETURN(value_visitor{lib::forward(visitor)}) - - public: - template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), - lib::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, - Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN( - alt::visit_alt_at(index, - lib::forward(visitor), - lib::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN( - visit_alt(make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) - - template - inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, - Visitor &&visitor, - Vs &&... vs) - DECLTYPE_AUTO_RETURN( - visit_alt_at(index, - make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) - }; - - } // namespace visitation - - template - struct alt { - using value_type = T; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - template - inline explicit constexpr alt(in_place_t, Args &&... args) - : value(lib::forward(args)...) {} -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - T value; - }; - - template - union recursive_union; - - template - union recursive_union {}; - -#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ - template \ - union recursive_union { \ - public: \ - inline explicit constexpr recursive_union(valueless_t) noexcept \ - : dummy_{} {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t<0>, \ - Args &&... args) \ - : head_(in_place_t{}, lib::forward(args)...) {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t, \ - Args &&... args) \ - : tail_(in_place_index_t{}, lib::forward(args)...) {} \ - \ - recursive_union(const recursive_union &) = default; \ - recursive_union(recursive_union &&) = default; \ - \ - destructor \ - \ - recursive_union &operator=(const recursive_union &) = default; \ - recursive_union &operator=(recursive_union &&) = default; \ - \ - private: \ - char dummy_; \ - alt head_; \ - recursive_union tail_; \ - \ - friend struct access::recursive_union; \ - } - - MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, - ~recursive_union() = default;); - MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, - ~recursive_union() {}); - MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, - ~recursive_union() = delete;); - -#undef MPARK_VARIANT_RECURSIVE_UNION - - template - using index_t = typename std::conditional< - sizeof...(Ts) < (std::numeric_limits::max)(), - unsigned char, - typename std::conditional< - sizeof...(Ts) < (std::numeric_limits::max)(), - unsigned short, - unsigned int>::type - >::type; - - template - class base { - public: - inline explicit constexpr base(valueless_t tag) noexcept - : data_(tag), index_(static_cast>(-1)) {} - - template - inline explicit constexpr base(in_place_index_t, Args &&... args) - : data_(in_place_index_t{}, lib::forward(args)...), - index_(I) {} - - inline constexpr bool valueless_by_exception() const noexcept { - return index_ == static_cast>(-1); - } - - inline constexpr std::size_t index() const noexcept { - return valueless_by_exception() ? variant_npos : index_; - } - - protected: - using data_t = recursive_union; - - friend inline constexpr base &as_base(base &b) { return b; } - friend inline constexpr const base &as_base(const base &b) { return b; } - friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } - friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } - - friend inline constexpr data_t &data(base &b) { return b.data_; } - friend inline constexpr const data_t &data(const base &b) { return b.data_; } - friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } - friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } - - inline static constexpr std::size_t size() { return sizeof...(Ts); } - - data_t data_; - index_t index_; - - friend struct access::base; - friend struct visitation::base; - }; - - struct dtor { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif - template - inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - }; - -#if !defined(_MSC_VER) || _MSC_VER >= 1910 -#define MPARK_INHERITING_CTOR(type, base) using base::base; -#else -#define MPARK_INHERITING_CTOR(type, base) \ - template \ - inline explicit constexpr type(Args &&... args) \ - : base(lib::forward(args)...) {} -#endif - - template - class destructor; - -#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ - template \ - class destructor, destructible_trait> \ - : public base { \ - using super = base; \ - \ - public: \ - MPARK_INHERITING_CTOR(destructor, super) \ - using super::operator=; \ - \ - destructor(const destructor &) = default; \ - destructor(destructor &&) = default; \ - definition \ - destructor &operator=(const destructor &) = default; \ - destructor &operator=(destructor &&) = default; \ - \ - protected: \ - destroy \ - } - - MPARK_VARIANT_DESTRUCTOR( - Trait::TriviallyAvailable, - ~destructor() = default;, - inline void destroy() noexcept { - this->index_ = static_cast>(-1); - }); - - MPARK_VARIANT_DESTRUCTOR( - Trait::Available, - ~destructor() { destroy(); }, - inline void destroy() noexcept { - if (!this->valueless_by_exception()) { - visitation::alt::visit_alt(dtor{}, *this); - } - this->index_ = static_cast>(-1); - }); - - MPARK_VARIANT_DESTRUCTOR( - Trait::Unavailable, - ~destructor() = delete;, - inline void destroy() noexcept = delete;); - -#undef MPARK_VARIANT_DESTRUCTOR - - template - class constructor : public destructor { - using super = destructor; - - public: - MPARK_INHERITING_CTOR(constructor, super) - using super::operator=; - - protected: - struct ctor { - template - inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { - constructor::construct_alt(lhs_alt, - lib::forward(rhs_alt).value); - } - }; - - template - inline static T &construct_alt(alt &a, Args &&... args) { - auto *result = ::new (static_cast(lib::addressof(a))) - alt(in_place_t{}, lib::forward(args)...); - return result->value; - } - - template - inline static void generic_construct(constructor &lhs, Rhs &&rhs) { - lhs.destroy(); - if (!rhs.valueless_by_exception()) { - visitation::alt::visit_alt_at( - rhs.index(), - ctor{} - , - lhs, - lib::forward(rhs)); - lhs.index_ = rhs.index_; - } - } - }; - - template - class move_constructor; - -#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ - template \ - class move_constructor, move_constructible_trait> \ - : public constructor> { \ - using super = constructor>; \ - \ - public: \ - MPARK_INHERITING_CTOR(move_constructor, super) \ - using super::operator=; \ - \ - move_constructor(const move_constructor &) = default; \ - definition \ - ~move_constructor() = default; \ - move_constructor &operator=(const move_constructor &) = default; \ - move_constructor &operator=(move_constructor &&) = default; \ - } - - MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::TriviallyAvailable, - move_constructor(move_constructor &&that) = default;); - - MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::Available, - move_constructor(move_constructor &&that) noexcept( - lib::all::value...>::value) - : move_constructor(valueless_t{}) { - this->generic_construct(*this, lib::move(that)); - }); - - MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::Unavailable, - move_constructor(move_constructor &&) = delete;); - -#undef MPARK_VARIANT_MOVE_CONSTRUCTOR - - template - class copy_constructor; - -#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ - template \ - class copy_constructor, copy_constructible_trait> \ - : public move_constructor> { \ - using super = move_constructor>; \ - \ - public: \ - MPARK_INHERITING_CTOR(copy_constructor, super) \ - using super::operator=; \ - \ - definition \ - copy_constructor(copy_constructor &&) = default; \ - ~copy_constructor() = default; \ - copy_constructor &operator=(const copy_constructor &) = default; \ - copy_constructor &operator=(copy_constructor &&) = default; \ - } - - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::TriviallyAvailable, - copy_constructor(const copy_constructor &that) = default;); - - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Available, - copy_constructor(const copy_constructor &that) - : copy_constructor(valueless_t{}) { - this->generic_construct(*this, that); - }); - - MPARK_VARIANT_COPY_CONSTRUCTOR( - Trait::Unavailable, - copy_constructor(const copy_constructor &) = delete;); - -#undef MPARK_VARIANT_COPY_CONSTRUCTOR - - template - class assignment : public copy_constructor { - using super = copy_constructor; - - public: - MPARK_INHERITING_CTOR(assignment, super) - using super::operator=; - - template - inline /* auto & */ auto emplace(Args &&... args) - -> decltype(this->construct_alt(access::base::get_alt(*this), - lib::forward(args)...)) { - this->destroy(); - auto &result = this->construct_alt(access::base::get_alt(*this), - lib::forward(args)...); - this->index_ = I; - return result; - } - - protected: - template - struct assigner { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { - self->assign_alt(this_alt, lib::forward(that_alt).value); - } - assignment *self; - }; - - template - inline void assign_alt(alt &a, Arg &&arg) { - if (this->index() == I) { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - a.value = lib::forward(arg); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - } else { - struct { - void operator()(std::true_type) const { - this_->emplace(lib::forward(arg_)); - } - void operator()(std::false_type) const { - this_->emplace(T(lib::forward(arg_))); - } - assignment *this_; - Arg &&arg_; - } impl{this, lib::forward(arg)}; - impl(lib::bool_constant< - std::is_nothrow_constructible::value || - !std::is_nothrow_move_constructible::value>{}); - } - } - - template - inline void generic_assign(That &&that) { - if (this->valueless_by_exception() && that.valueless_by_exception()) { - // do nothing. - } else if (that.valueless_by_exception()) { - this->destroy(); - } else { - visitation::alt::visit_alt_at( - that.index(), - assigner{this} - , - *this, - lib::forward(that)); - } - } - }; - - template - class move_assignment; - -#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ - template \ - class move_assignment, move_assignable_trait> \ - : public assignment> { \ - using super = assignment>; \ - \ - public: \ - MPARK_INHERITING_CTOR(move_assignment, super) \ - using super::operator=; \ - \ - move_assignment(const move_assignment &) = default; \ - move_assignment(move_assignment &&) = default; \ - ~move_assignment() = default; \ - move_assignment &operator=(const move_assignment &) = default; \ - definition \ - } - - MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::TriviallyAvailable, - move_assignment &operator=(move_assignment &&that) = default;); - - MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::Available, - move_assignment & - operator=(move_assignment &&that) noexcept( - lib::all<(std::is_nothrow_move_constructible::value && - std::is_nothrow_move_assignable::value)...>::value) { - this->generic_assign(lib::move(that)); - return *this; - }); - - MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::Unavailable, - move_assignment &operator=(move_assignment &&) = delete;); - -#undef MPARK_VARIANT_MOVE_ASSIGNMENT - - template - class copy_assignment; - -#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ - template \ - class copy_assignment, copy_assignable_trait> \ - : public move_assignment> { \ - using super = move_assignment>; \ - \ - public: \ - MPARK_INHERITING_CTOR(copy_assignment, super) \ - using super::operator=; \ - \ - copy_assignment(const copy_assignment &) = default; \ - copy_assignment(copy_assignment &&) = default; \ - ~copy_assignment() = default; \ - definition \ - copy_assignment &operator=(copy_assignment &&) = default; \ - } - - MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::TriviallyAvailable, - copy_assignment &operator=(const copy_assignment &that) = default;); - - MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::Available, - copy_assignment &operator=(const copy_assignment &that) { - this->generic_assign(that); - return *this; - }); - - MPARK_VARIANT_COPY_ASSIGNMENT( - Trait::Unavailable, - copy_assignment &operator=(const copy_assignment &) = delete;); - -#undef MPARK_VARIANT_COPY_ASSIGNMENT - - template - class impl : public copy_assignment> { - using super = copy_assignment>; - - public: - MPARK_INHERITING_CTOR(impl, super) - using super::operator=; - - impl(const impl&) = default; - impl(impl&&) = default; - ~impl() = default; - impl &operator=(const impl &) = default; - impl &operator=(impl &&) = default; - - template - inline void assign(Arg &&arg) { - this->assign_alt(access::base::get_alt(*this), - lib::forward(arg)); - } - - inline void swap(impl &that) { - if (this->valueless_by_exception() && that.valueless_by_exception()) { - // do nothing. - } else if (this->index() == that.index()) { - visitation::alt::visit_alt_at(this->index(), - swapper{} - , - *this, - that); - } else { - impl *lhs = this; - impl *rhs = lib::addressof(that); - if (lhs->move_nothrow() && !rhs->move_nothrow()) { - std::swap(lhs, rhs); - } - impl tmp(lib::move(*rhs)); -#ifdef MPARK_EXCEPTIONS - // EXTENSION: When the move construction of `lhs` into `rhs` throws - // and `tmp` is nothrow move constructible then we move `tmp` back - // into `rhs` and provide the strong exception safety guarantee. - try { - this->generic_construct(*rhs, lib::move(*lhs)); - } catch (...) { - if (tmp.move_nothrow()) { - this->generic_construct(*rhs, lib::move(tmp)); - } - throw; - } -#else - this->generic_construct(*rhs, lib::move(*lhs)); -#endif - this->generic_construct(*lhs, lib::move(tmp)); - } - } - - private: - struct swapper { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { - using std::swap; - swap(this_alt.value, that_alt.value); - } - }; - - inline constexpr bool move_nothrow() const { - return this->valueless_by_exception() || - lib::array{ - {std::is_nothrow_move_constructible::value...} - }[this->index()]; - } - }; - -#undef MPARK_INHERITING_CTOR - - template - struct is_non_narrowing_convertible { - template - static std::true_type test(T(&&)[1]); - - template - static auto impl(int) -> decltype(test({std::declval()})); - - template - static auto impl(...) -> std::false_type; - - static constexpr bool value = decltype(impl(0))::value; - }; - - template ::value, - typename = void> - struct overload_leaf {}; - - template - struct overload_leaf { - using impl = lib::size_constant (*)(T); - operator impl() const { return nullptr; }; - }; - - template - struct overload_leaf< - Arg, - I, - T, - true -#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5 - , - lib::enable_if_t< - std::is_same, bool>::value - ? std::is_same, bool>::value - : is_non_narrowing_convertible::value> -#endif - > { - using impl = lib::size_constant (*)(T); - operator impl() const { return nullptr; }; - }; - - template - struct overload_impl { - private: - template - struct impl; - - template - struct impl> : overload_leaf... {}; - - public: - using type = impl>; - }; - - template - using overload = typename overload_impl::type; - - template - using best_match = lib::invoke_result_t, Arg>; - - template - struct is_in_place_index : std::false_type {}; - - template - struct is_in_place_index> : std::true_type {}; - - template - struct is_in_place_type : std::false_type {}; - - template - struct is_in_place_type> : std::true_type {}; - - } // detail - - template - class variant { - static_assert(0 < sizeof...(Ts), - "variant must consist of at least one alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have an array type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a reference type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a void type as an alternative."); - - public: - template < - typename Front = lib::type_pack_element_t<0, Ts...>, - lib::enable_if_t::value, int> = 0> - inline constexpr variant() noexcept( - std::is_nothrow_default_constructible::value) - : impl_(in_place_index_t<0>{}) {} - - variant(const variant &) = default; - variant(variant &&) = default; - - template < - typename Arg, - typename Decayed = lib::decay_t, - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t::value, int> = 0> - inline constexpr variant(Arg &&arg) noexcept( - std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(arg)) {} - - template < - std::size_t I, - typename... Args, - typename T = lib::type_pack_element_t, - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant( - in_place_index_t, - Args &&... args) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) {} - - template < - std::size_t I, - typename Up, - typename... Args, - typename T = lib::type_pack_element_t, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline explicit constexpr variant( - in_place_index_t, - std::initializer_list il, - Args &&... args) noexcept(std:: - is_nothrow_constructible< - T, - std::initializer_list &, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) {} - - template < - typename T, - typename... Args, - std::size_t I = detail::find_index_sfinae::value, - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant( - in_place_type_t, - Args &&... args) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) {} - - template < - typename T, - typename Up, - typename... Args, - std::size_t I = detail::find_index_sfinae::value, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline explicit constexpr variant( - in_place_type_t, - std::initializer_list il, - Args &&... args) noexcept(std:: - is_nothrow_constructible< - T, - std::initializer_list &, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) {} - - ~variant() = default; - - variant &operator=(const variant &) = default; - variant &operator=(variant &&) = default; - - template , variant>::value, - int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t<(std::is_assignable::value && - std::is_constructible::value), - int> = 0> - inline variant &operator=(Arg &&arg) noexcept( - (std::is_nothrow_assignable::value && - std::is_nothrow_constructible::value)) { - impl_.template assign(lib::forward(arg)); - return *this; - } - - template < - std::size_t I, - typename... Args, - typename T = lib::type_pack_element_t, - lib::enable_if_t::value, int> = 0> - inline T &emplace(Args &&... args) { - return impl_.template emplace(lib::forward(args)...); - } - - template < - std::size_t I, - typename Up, - typename... Args, - typename T = lib::type_pack_element_t, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline T &emplace(std::initializer_list il, Args &&... args) { - return impl_.template emplace(il, lib::forward(args)...); - } - - template < - typename T, - typename... Args, - std::size_t I = detail::find_index_sfinae::value, - lib::enable_if_t::value, int> = 0> - inline T &emplace(Args &&... args) { - return impl_.template emplace(lib::forward(args)...); - } - - template < - typename T, - typename Up, - typename... Args, - std::size_t I = detail::find_index_sfinae::value, - lib::enable_if_t &, - Args...>::value, - int> = 0> - inline T &emplace(std::initializer_list il, Args &&... args) { - return impl_.template emplace(il, lib::forward(args)...); - } - - inline constexpr bool valueless_by_exception() const noexcept { - return impl_.valueless_by_exception(); - } - - inline constexpr std::size_t index() const noexcept { - return impl_.index(); - } - - template , - Dummy>::value && - lib::dependent_type, - Dummy>::value)...>::value, - int> = 0> - inline void swap(variant &that) noexcept( - lib::all<(std::is_nothrow_move_constructible::value && - lib::is_nothrow_swappable::value)...>::value) { - impl_.swap(that.impl_); - } - - private: - detail::impl impl_; - - friend struct detail::access::variant; - friend struct detail::visitation::variant; - }; - - template - inline constexpr bool holds_alternative(const variant &v) noexcept { - return v.index() == I; - } - - template - inline constexpr bool holds_alternative(const variant &v) noexcept { - return holds_alternative::value>(v); - } - - namespace detail { - template - struct generic_get_impl { - constexpr generic_get_impl(int) noexcept {} - - constexpr AUTO_REFREF operator()(V &&v) const - AUTO_REFREF_RETURN( - access::variant::get_alt(lib::forward(v)).value) - }; - - template - inline constexpr AUTO_REFREF generic_get(V &&v) - AUTO_REFREF_RETURN(generic_get_impl( - holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))( - lib::forward(v))) - } // namespace detail - - template - inline constexpr variant_alternative_t> &get( - variant &v) { - return detail::generic_get(v); - } - - template - inline constexpr variant_alternative_t> &&get( - variant &&v) { - return detail::generic_get(lib::move(v)); - } - - template - inline constexpr const variant_alternative_t> &get( - const variant &v) { - return detail::generic_get(v); - } - - template - inline constexpr const variant_alternative_t> &&get( - const variant &&v) { - return detail::generic_get(lib::move(v)); - } - - template - inline constexpr T &get(variant &v) { - return get::value>(v); - } - - template - inline constexpr T &&get(variant &&v) { - return get::value>(lib::move(v)); - } - - template - inline constexpr const T &get(const variant &v) { - return get::value>(v); - } - - template - inline constexpr const T &&get(const variant &&v) { - return get::value>(lib::move(v)); - } - - namespace detail { - - template - inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept - AUTO_RETURN(v && holds_alternative(*v) - ? lib::addressof(access::variant::get_alt(*v).value) - : nullptr) - - } // namespace detail - - template - inline constexpr lib::add_pointer_t>> - get_if(variant *v) noexcept { - return detail::generic_get_if(v); - } - - template - inline constexpr lib::add_pointer_t< - const variant_alternative_t>> - get_if(const variant *v) noexcept { - return detail::generic_get_if(v); - } - - template - inline constexpr lib::add_pointer_t - get_if(variant *v) noexcept { - return get_if::value>(v); - } - - template - inline constexpr lib::add_pointer_t - get_if(const variant *v) noexcept { - return get_if::value>(v); - } - - namespace detail { - template - struct convert_to_bool { - template - inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const { - static_assert(std::is_convertible, - bool>::value, - "relational operators must return a type" - " implicitly convertible to bool"); - return lib::invoke( - RelOp{}, lib::forward(lhs), lib::forward(rhs)); - } - }; - } // namespace detail - - template - inline constexpr bool operator==(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using equal_to = detail::convert_to_bool; - return lhs.index() == rhs.index() && - (lhs.valueless_by_exception() || - variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); - } - - template - inline constexpr bool operator!=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using not_equal_to = detail::convert_to_bool; - return lhs.index() != rhs.index() || - (!lhs.valueless_by_exception() && - variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); - } - - template - inline constexpr bool operator<(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using less = detail::convert_to_bool; - return !rhs.valueless_by_exception() && - (lhs.valueless_by_exception() || lhs.index() < rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); - } - - template - inline constexpr bool operator>(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using greater = detail::convert_to_bool; - return !lhs.valueless_by_exception() && - (rhs.valueless_by_exception() || lhs.index() > rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); - } - - template - inline constexpr bool operator<=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using less_equal = detail::convert_to_bool; - return lhs.valueless_by_exception() || - (!rhs.valueless_by_exception() && - (lhs.index() < rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); - } - - template - inline constexpr bool operator>=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using greater_equal = detail::convert_to_bool; - return rhs.valueless_by_exception() || - (!lhs.valueless_by_exception() && - (lhs.index() > rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at( - lhs.index(), greater_equal{}, lhs, rhs)))); - } - - struct monostate {}; - - inline constexpr bool operator<(monostate, monostate) noexcept { - return false; - } - - inline constexpr bool operator>(monostate, monostate) noexcept { - return false; - } - - inline constexpr bool operator<=(monostate, monostate) noexcept { - return true; - } - - inline constexpr bool operator>=(monostate, monostate) noexcept { - return true; - } - - inline constexpr bool operator==(monostate, monostate) noexcept { - return true; - } - - inline constexpr bool operator!=(monostate, monostate) noexcept { - return false; - } - - namespace detail { - - template - inline constexpr bool all_impl(const lib::array &bs, - std::size_t idx) { - return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); - } - - template - inline constexpr bool all(const lib::array &bs) { - return all_impl(bs, 0); - } - - } // namespace detail - - template - inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) - DECLTYPE_AUTO_RETURN( - (detail::all( - lib::array{{!vs.valueless_by_exception()...}}) - ? (void)0 - : throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...)) - template - inline auto swap(variant &lhs, - variant &rhs) noexcept(noexcept(lhs.swap(rhs))) - -> decltype(lhs.swap(rhs)) { - lhs.swap(rhs); - } - - namespace detail { - - template - using enabled_type = T; - - namespace hash { - - template - constexpr bool meets_requirements() noexcept { - return std::is_copy_constructible::value && - std::is_move_constructible::value && - lib::is_invocable_r::value; - } - - template - constexpr bool is_enabled() noexcept { - using H = std::hash; - return meets_requirements() && - std::is_default_constructible::value && - std::is_copy_assignable::value && - std::is_move_assignable::value; - } - - } // namespace hash - - } // namespace detail - -#undef AUTO -#undef AUTO_RETURN - -#undef AUTO_REFREF -#undef AUTO_REFREF_RETURN - -#undef DECLTYPE_AUTO -#undef DECLTYPE_AUTO_RETURN - -} // namespace nostd -OPENTELEMETRY_END_NAMESPACE - -namespace std { - - template - struct hash, - mpark::lib::enable_if_t>()...>::value>>> { - using argument_type = mpark::variant; - using result_type = std::size_t; - - inline result_type operator()(const argument_type &v) const { - using mpark::detail::visitation::variant; - std::size_t result = - v.valueless_by_exception() - ? 299792458 // Random value chosen by the universe upon creation - : variant::visit_alt( - hasher{} - , - v); - return hash_combine(result, hash{}(v.index())); - } - - private: - struct hasher { - template - inline std::size_t operator()(const Alt &alt) const { - using alt_type = mpark::lib::decay_t; - using value_type = - mpark::lib::remove_const_t; - return hash{}(alt.value); - } - }; - - static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { - return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); - } - }; - - template <> - struct hash { - using argument_type = mpark::monostate; - using result_type = std::size_t; - - inline result_type operator()(const argument_type &) const noexcept { - return 66740831; // return a fundamentally attractive random value. - } - }; - -} // namespace std From 4b0b985c65a96c32df9027abb8c5aa65dff6bde0 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 11:54:32 -0700 Subject: [PATCH 17/42] Rename --- .../opentelemetry/nostd/detail/functional.h | 16 +++--- .../opentelemetry/nostd/detail/invoke.h | 22 ++++---- .../nostd/detail/recursive_union.h | 10 ++-- api/include/opentelemetry/nostd/variant.h | 50 +++++++++---------- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/functional.h b/api/include/opentelemetry/nostd/detail/functional.h index a426e5358d..067a7ff78e 100644 --- a/api/include/opentelemetry/nostd/detail/functional.h +++ b/api/include/opentelemetry/nostd/detail/functional.h @@ -4,7 +4,7 @@ #include "opentelemetry/version.h" -#define MPARK_RETURN(...) \ +#define OPENTELEMETRY_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } OPENTELEMETRY_BEGIN_NAMESPACE @@ -16,45 +16,45 @@ struct equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) == std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) == std::forward(rhs)) }; struct not_equal_to { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) != std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) != std::forward(rhs)) }; struct less { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) < std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) < std::forward(rhs)) }; struct greater { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) > std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) > std::forward(rhs)) }; struct less_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) <= std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) <= std::forward(rhs)) }; struct greater_equal { template inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const - MPARK_RETURN(std::forward(lhs) >= std::forward(rhs)) + OPENTELEMETRY_RETURN(std::forward(lhs) >= std::forward(rhs)) }; } // namespace detail } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#undef MPARK_RETURN +#undef OPENTELEMETRY_RETURN diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h index 7e7be3c3b7..f285b3e8e4 100644 --- a/api/include/opentelemetry/nostd/detail/invoke.h +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -7,7 +7,7 @@ #include "opentelemetry/nostd/detail/void.h" #include "opentelemetry/version.h" -#define MPARK_RETURN(...) \ +#define OPENTELEMETRY_RETURN(...) \ noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } OPENTELEMETRY_BEGIN_NAMESPACE @@ -32,7 +32,7 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN((std::forward(arg).*pmf)(std::forward(args)...)) + OPENTELEMETRY_RETURN((std::forward(arg).*pmf)(std::forward(args)...)) }; template <> @@ -40,7 +40,7 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN((std::forward(arg).get().*pmf)(std::forward(args)...)) + OPENTELEMETRY_RETURN((std::forward(arg).get().*pmf)(std::forward(args)...)) }; template <> @@ -48,7 +48,7 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args) - MPARK_RETURN(((*std::forward(arg)).*pmf)(std::forward(args)...)) + OPENTELEMETRY_RETURN(((*std::forward(arg)).*pmf)(std::forward(args)...)) }; template <> @@ -56,7 +56,7 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(std::forward(arg).*pmo) + OPENTELEMETRY_RETURN(std::forward(arg).*pmo) }; template <> @@ -64,7 +64,7 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN(std::forward(arg).get().*pmo) + OPENTELEMETRY_RETURN(std::forward(arg).get().*pmo) }; template <> @@ -72,12 +72,12 @@ struct Invoke { template inline static constexpr auto invoke(R T::*pmo, Arg &&arg) - MPARK_RETURN((*std::forward(arg)).*pmo) + OPENTELEMETRY_RETURN((*std::forward(arg)).*pmo) }; template inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args) - MPARK_RETURN(Invoke::value, + OPENTELEMETRY_RETURN(Invoke::value, (std::is_base_of>::value ? 0 : is_reference_wrapper>::value ? 1 : 2)>:: @@ -89,7 +89,7 @@ inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args) #endif template inline constexpr auto invoke_impl(F &&f, Args &&... args) - MPARK_RETURN(std::forward(f)(std::forward(args)...)) + OPENTELEMETRY_RETURN(std::forward(f)(std::forward(args)...)) #ifdef _MSC_VER # pragma warning(pop) #endif @@ -97,7 +97,7 @@ inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args) template inline constexpr auto invoke(F &&f, Args &&... args) - MPARK_RETURN(detail::invoke_impl(std::forward(f), std::forward(args)...)); + OPENTELEMETRY_RETURN(detail::invoke_impl(std::forward(f), std::forward(args)...)); namespace detail { @@ -152,4 +152,4 @@ using is_invocable_r = detail::is_invocable_r; } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#undef MPARK_RETURN +#undef OPENTELEMETRY_RETURN diff --git a/api/include/opentelemetry/nostd/detail/recursive_union.h b/api/include/opentelemetry/nostd/detail/recursive_union.h index 2a3cf53643..a412465302 100644 --- a/api/include/opentelemetry/nostd/detail/recursive_union.h +++ b/api/include/opentelemetry/nostd/detail/recursive_union.h @@ -72,7 +72,7 @@ template union recursive_union {}; -#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ +#define OPENTELEMETRY_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ template \ union recursive_union \ { \ @@ -106,11 +106,11 @@ union recursive_union friend struct access::recursive_union; \ } -MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){}); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); +OPENTELEMETRY_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;); +OPENTELEMETRY_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){}); +OPENTELEMETRY_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); -#undef MPARK_VARIANT_RECURSIVE_UNION +#undef OPENTELEMETRY_VARIANT_RECURSIVE_UNION } // namespace detail } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 989eb13446..10621ceb77 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -372,7 +372,7 @@ struct dtor template class destructor; -#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ +#define OPENTELEMETRY_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ template \ class destructor, destructible_trait> : public base \ { \ @@ -391,11 +391,11 @@ class destructor; destroy \ } -MPARK_VARIANT_DESTRUCTOR( +OPENTELEMETRY_VARIANT_DESTRUCTOR( Trait::TriviallyAvailable, ~destructor() = default; , inline void destroy() noexcept { this->index_ = static_cast>(-1); }); -MPARK_VARIANT_DESTRUCTOR( +OPENTELEMETRY_VARIANT_DESTRUCTOR( Trait::Available, ~destructor() { destroy(); }, inline void destroy() noexcept { @@ -406,10 +406,10 @@ MPARK_VARIANT_DESTRUCTOR( this->index_ = static_cast>(-1); }); -MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; +OPENTELEMETRY_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; , inline void destroy() noexcept = delete;); -#undef MPARK_VARIANT_DESTRUCTOR +#undef OPENTELEMETRY_VARIANT_DESTRUCTOR template class constructor : public destructor @@ -453,7 +453,7 @@ class constructor : public destructor template class move_constructor; -#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ +#define OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ template \ class move_constructor, move_constructible_trait> \ : public constructor> \ @@ -470,23 +470,23 @@ class move_constructor; move_constructor &operator=(move_constructor &&) = default; \ } -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, +OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, move_constructor(move_constructor &&that) = default;); -MPARK_VARIANT_MOVE_CONSTRUCTOR( +OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR( Trait::Available, move_constructor(move_constructor &&that) noexcept( all::value...>::value) : move_constructor(valueless_t{}) { this->generic_construct(*this, std::move(that)); }); -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor &&) = delete;); +OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor &&) = delete;); -#undef MPARK_VARIANT_MOVE_CONSTRUCTOR +#undef OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR template class copy_constructor; -#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ +#define OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ template \ class copy_constructor, copy_constructible_trait> \ : public move_constructor> \ @@ -503,17 +503,17 @@ class copy_constructor; copy_constructor &operator=(copy_constructor &&) = default; \ } -MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable, +OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable, copy_constructor(const copy_constructor &that) = default;); -MPARK_VARIANT_COPY_CONSTRUCTOR( +OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR( Trait::Available, copy_constructor(const copy_constructor &that) : copy_constructor(valueless_t{}) { this->generic_construct(*this, that); }); -MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable, +OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable, copy_constructor(const copy_constructor &) = delete;); -#undef MPARK_VARIANT_COPY_CONSTRUCTOR +#undef OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR template class assignment : public copy_constructor @@ -597,7 +597,7 @@ class assignment : public copy_constructor template class move_assignment; -#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ +#define OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ template \ class move_assignment, move_assignable_trait> : public assignment> \ { \ @@ -614,10 +614,10 @@ class move_assignment; definition \ } -MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, +OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, move_assignment &operator=(move_assignment &&that) = default;); -MPARK_VARIANT_MOVE_ASSIGNMENT( +OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT( Trait::Available, move_assignment & operator=(move_assignment &&that) noexcept( @@ -627,15 +627,15 @@ MPARK_VARIANT_MOVE_ASSIGNMENT( return *this; }); -MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, +OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, move_assignment &operator=(move_assignment &&) = delete;); -#undef MPARK_VARIANT_MOVE_ASSIGNMENT +#undef OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT template class copy_assignment; -#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ +#define OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ template \ class copy_assignment, copy_assignable_trait> \ : public move_assignment> \ @@ -652,10 +652,10 @@ class copy_assignment; definition copy_assignment &operator=(copy_assignment &&) = default; \ } -MPARK_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable, +OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable, copy_assignment &operator=(const copy_assignment &that) = default;); -MPARK_VARIANT_COPY_ASSIGNMENT( +OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT( Trait::Available, copy_assignment & operator=(const copy_assignment &that) { @@ -663,10 +663,10 @@ MPARK_VARIANT_COPY_ASSIGNMENT( return *this; }); -MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable, +OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable, copy_assignment &operator=(const copy_assignment &) = delete;); -#undef MPARK_VARIANT_COPY_ASSIGNMENT +#undef OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT template class impl : public copy_assignment> { From aeefb7ab717a5a934227a6e469deee428ef87e69 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 11:55:23 -0700 Subject: [PATCH 18/42] Reformat --- .../opentelemetry/nostd/detail/decay.h | 2 +- .../nostd/detail/dependent_type.h | 1 - .../opentelemetry/nostd/detail/find_index.h | 2 +- .../opentelemetry/nostd/detail/functional.h | 2 +- .../opentelemetry/nostd/detail/invoke.h | 30 ++-- .../nostd/detail/recursive_union.h | 9 +- .../opentelemetry/nostd/detail/valueless.h | 3 +- .../nostd/detail/variant_alternative.h | 2 +- api/include/opentelemetry/nostd/type_traits.h | 12 +- api/include/opentelemetry/nostd/utility.h | 19 ++- api/include/opentelemetry/nostd/variant.h | 132 +++++++++--------- api/test/nostd/utility_test.cc | 3 +- api/test/nostd/variant_test.cc | 28 ++-- 13 files changed, 130 insertions(+), 115 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/decay.h b/api/include/opentelemetry/nostd/detail/decay.h index 14df2dcd4a..23aaaee2eb 100644 --- a/api/include/opentelemetry/nostd/detail/decay.h +++ b/api/include/opentelemetry/nostd/detail/decay.h @@ -7,7 +7,7 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -template< class T > +template using decay_t = typename std::decay::type; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/dependent_type.h b/api/include/opentelemetry/nostd/detail/dependent_type.h index c2b366633f..0f58bcf7f7 100644 --- a/api/include/opentelemetry/nostd/detail/dependent_type.h +++ b/api/include/opentelemetry/nostd/detail/dependent_type.h @@ -15,4 +15,3 @@ struct dependent_type : T } // namespace detail } // namespace nostd OPENTELEMETRY_END_NAMESPACE - diff --git a/api/include/opentelemetry/nostd/detail/find_index.h b/api/include/opentelemetry/nostd/detail/find_index.h index e5fe9657c1..20d2c64a4e 100644 --- a/api/include/opentelemetry/nostd/detail/find_index.h +++ b/api/include/opentelemetry/nostd/detail/find_index.h @@ -2,8 +2,8 @@ #include -#include "opentelemetry/nostd/utility.h" #include "opentelemetry/nostd/type_traits.h" +#include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/functional.h b/api/include/opentelemetry/nostd/detail/functional.h index 067a7ff78e..a3546f2bee 100644 --- a/api/include/opentelemetry/nostd/detail/functional.h +++ b/api/include/opentelemetry/nostd/detail/functional.h @@ -5,7 +5,7 @@ #include "opentelemetry/version.h" #define OPENTELEMETRY_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd diff --git a/api/include/opentelemetry/nostd/detail/invoke.h b/api/include/opentelemetry/nostd/detail/invoke.h index f285b3e8e4..e713d93dbe 100644 --- a/api/include/opentelemetry/nostd/detail/invoke.h +++ b/api/include/opentelemetry/nostd/detail/invoke.h @@ -78,10 +78,10 @@ struct Invoke template inline constexpr auto invoke_impl(R T::*f, Arg &&arg, Args &&... args) OPENTELEMETRY_RETURN(Invoke::value, - (std::is_base_of>::value - ? 0 - : is_reference_wrapper>::value ? 1 : 2)>:: - invoke(f, std::forward(arg), std::forward(args)...)) + (std::is_base_of>::value + ? 0 + : is_reference_wrapper>::value ? 1 : 2)>:: + invoke(f, std::forward(arg), std::forward(args)...)) #ifdef _MSC_VER # pragma warning(push) @@ -102,17 +102,17 @@ inline constexpr auto invoke(F &&f, Args &&... args) namespace detail { - template - struct invoke_result - {}; - - template - struct invoke_result(), std::declval()...))>, - F, - Args...> - { - using type = decltype(nostd::invoke(std::declval(), std::declval()...)); - }; +template +struct invoke_result +{}; + +template +struct invoke_result(), std::declval()...))>, + F, + Args...> +{ + using type = decltype(nostd::invoke(std::declval(), std::declval()...)); +}; } // namespace detail diff --git a/api/include/opentelemetry/nostd/detail/recursive_union.h b/api/include/opentelemetry/nostd/detail/recursive_union.h index a412465302..c03cf4cd23 100644 --- a/api/include/opentelemetry/nostd/detail/recursive_union.h +++ b/api/include/opentelemetry/nostd/detail/recursive_union.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "opentelemetry/nostd/detail/trait.h" #include "opentelemetry/nostd/detail/valueless.h" @@ -36,15 +36,14 @@ struct recursive_union struct get_alt_impl<0, Dummy> { template - inline constexpr auto operator()(V &&v) const - AUTO_REFREF_RETURN(std::forward(v).head_) + inline constexpr auto operator()(V &&v) const AUTO_REFREF_RETURN(std::forward(v).head_) }; template inline static constexpr auto get_alt(V &&v, in_place_index_t) AUTO_REFREF_RETURN(get_alt_impl{}(std::forward(v))) }; -} // namespace access +} // namespace access template struct alt @@ -72,7 +71,7 @@ template union recursive_union {}; -#define OPENTELEMETRY_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ +#define OPENTELEMETRY_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ template \ union recursive_union \ { \ diff --git a/api/include/opentelemetry/nostd/detail/valueless.h b/api/include/opentelemetry/nostd/detail/valueless.h index 8de535f4e8..2a89b575e2 100644 --- a/api/include/opentelemetry/nostd/detail/valueless.h +++ b/api/include/opentelemetry/nostd/detail/valueless.h @@ -5,6 +5,7 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -struct valueless_t {}; +struct valueless_t +{}; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/nostd/detail/variant_alternative.h b/api/include/opentelemetry/nostd/detail/variant_alternative.h index 1bc5037acf..70486cfc1a 100644 --- a/api/include/opentelemetry/nostd/detail/variant_alternative.h +++ b/api/include/opentelemetry/nostd/detail/variant_alternative.h @@ -2,8 +2,8 @@ #include -#include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/nostd/detail/type_pack_element.h" +#include "opentelemetry/nostd/detail/variant_fwd.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index d19f5db132..2fa9483d07 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -12,7 +12,7 @@ namespace nostd /** * Back port of std::add_pointer_t */ -template< class T > +template using add_pointer_t = typename std::add_pointer::type; /** @@ -90,8 +90,10 @@ using detail::swappable::is_swappable; /** * Back port of std::is_swappable */ -namespace detail { -namespace swappable { +namespace detail +{ +namespace swappable +{ template struct is_nothrow_swappable { @@ -101,8 +103,8 @@ struct is_nothrow_swappable template struct is_nothrow_swappable : std::false_type {}; -} // namespace swappable -} // namespace detail +} // namespace swappable +} // namespace detail template using is_nothrow_swappable = detail::swappable::is_nothrow_swappable::value, T>; } // namespace nostd diff --git a/api/include/opentelemetry/nostd/utility.h b/api/include/opentelemetry/nostd/utility.h index 27dcf2b6e8..d7fa3bfc19 100644 --- a/api/include/opentelemetry/nostd/utility.h +++ b/api/include/opentelemetry/nostd/utility.h @@ -82,12 +82,15 @@ using index_sequence = integer_sequence; /** * Back port of std::make_index_sequence */ -namespace detail { -template -struct index_sequence_push_back {}; +namespace detail +{ +template +struct index_sequence_push_back +{}; template -struct index_sequence_push_back, I> { +struct index_sequence_push_back, I> +{ using type = index_sequence; }; @@ -95,15 +98,17 @@ template using index_sequence_push_back_t = typename index_sequence_push_back::type; template -struct make_index_sequence_impl { +struct make_index_sequence_impl +{ using type = index_sequence_push_back_t::type, N - 1>; }; template <> -struct make_index_sequence_impl<0> { +struct make_index_sequence_impl<0> +{ using type = index_sequence<>; }; -} // namespace detail +} // namespace detail template using make_index_sequence = typename detail::make_index_sequence_impl::type; diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 10621ceb77..86f734c572 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -5,9 +5,9 @@ #include #include "opentelemetry/nostd/detail/all.h" -#include "opentelemetry/nostd/detail/functional.h" #include "opentelemetry/nostd/detail/dependent_type.h" #include "opentelemetry/nostd/detail/find_index.h" +#include "opentelemetry/nostd/detail/functional.h" #include "opentelemetry/nostd/detail/recursive_union.h" #include "opentelemetry/nostd/detail/trait.h" #include "opentelemetry/nostd/detail/type_pack_element.h" @@ -86,8 +86,8 @@ namespace visitation struct base { template - using dispatch_result_t = - decltype(nostd::invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); + using dispatch_result_t = decltype( + nostd::invoke(std::declval(), access::base::get_alt<0>(std::declval())...)); template struct expected @@ -107,7 +107,8 @@ struct base template inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Alts &&... alts) - DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), std::forward(alts)...)) + DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), + std::forward(alts)...)) }; template @@ -138,8 +139,8 @@ struct base inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) { using Expected = dispatch_result_t; - using Actual = - decltype(nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + using Actual = decltype( + nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -173,8 +174,8 @@ struct base inline static constexpr dispatch_result_t dispatch(F &&f, Vs &&... vs) { using Expected = dispatch_result_t; - using Actual = - decltype(nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); + using Actual = decltype( + nostd::invoke(std::forward(f), access::base::get_alt(std::forward(vs))...)); return visit_return_type_check::invoke( std::forward(f), access::base::get_alt(std::forward(vs))...); } @@ -256,7 +257,7 @@ struct variant inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), - std::forward(values)...)) + std::forward(values)...)) }; template @@ -372,7 +373,7 @@ struct dtor template class destructor; -#define OPENTELEMETRY_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ +#define OPENTELEMETRY_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ template \ class destructor, destructible_trait> : public base \ { \ @@ -407,7 +408,7 @@ OPENTELEMETRY_VARIANT_DESTRUCTOR( }); OPENTELEMETRY_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; - , inline void destroy() noexcept = delete;); + , inline void destroy() noexcept = delete;); #undef OPENTELEMETRY_VARIANT_DESTRUCTOR @@ -454,24 +455,24 @@ template class move_constructor; #define OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ - template \ - class move_constructor, move_constructible_trait> \ - : public constructor> \ - { \ - using super = constructor>; \ - \ - public: \ - using super::super; \ - using super::operator=; \ - \ - move_constructor(const move_constructor &) = default; \ - definition ~move_constructor() = default; \ - move_constructor &operator=(const move_constructor &) = default; \ - move_constructor &operator=(move_constructor &&) = default; \ + template \ + class move_constructor, move_constructible_trait> \ + : public constructor> \ + { \ + using super = constructor>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + move_constructor(const move_constructor &) = default; \ + definition ~move_constructor() = default; \ + move_constructor &operator=(const move_constructor &) = default; \ + move_constructor &operator=(move_constructor &&) = default; \ } OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, - move_constructor(move_constructor &&that) = default;); + move_constructor(move_constructor &&that) = default;); OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR( Trait::Available, @@ -479,7 +480,8 @@ OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR( all::value...>::value) : move_constructor(valueless_t{}) { this->generic_construct(*this, std::move(that)); }); -OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor &&) = delete;); +OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, + move_constructor(move_constructor &&) = delete;); #undef OPENTELEMETRY_VARIANT_MOVE_CONSTRUCTOR @@ -487,31 +489,31 @@ template class copy_constructor; #define OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ - template \ - class copy_constructor, copy_constructible_trait> \ - : public move_constructor> \ - { \ - using super = move_constructor>; \ - \ - public: \ - using super::super; \ - using super::operator=; \ - \ - definition copy_constructor(copy_constructor &&) = default; \ - ~copy_constructor() = default; \ - copy_constructor &operator=(const copy_constructor &) = default; \ - copy_constructor &operator=(copy_constructor &&) = default; \ + template \ + class copy_constructor, copy_constructible_trait> \ + : public move_constructor> \ + { \ + using super = move_constructor>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + definition copy_constructor(copy_constructor &&) = default; \ + ~copy_constructor() = default; \ + copy_constructor &operator=(const copy_constructor &) = default; \ + copy_constructor &operator=(copy_constructor &&) = default; \ } OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable, - copy_constructor(const copy_constructor &that) = default;); + copy_constructor(const copy_constructor &that) = default;); OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR( Trait::Available, copy_constructor(const copy_constructor &that) : copy_constructor(valueless_t{}) { this->generic_construct(*this, that); }); OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable, - copy_constructor(const copy_constructor &) = delete;); + copy_constructor(const copy_constructor &) = delete;); #undef OPENTELEMETRY_VARIANT_COPY_CONSTRUCTOR @@ -597,7 +599,7 @@ class assignment : public copy_constructor template class move_assignment; -#define OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ +#define OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ template \ class move_assignment, move_assignable_trait> : public assignment> \ { \ @@ -614,8 +616,8 @@ class move_assignment; definition \ } -OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, - move_assignment &operator=(move_assignment &&that) = default;); +OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT( + Trait::TriviallyAvailable, move_assignment &operator=(move_assignment &&that) = default;); OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT( Trait::Available, @@ -628,7 +630,7 @@ OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT( }); OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, - move_assignment &operator=(move_assignment &&) = delete;); + move_assignment &operator=(move_assignment &&) = delete;); #undef OPENTELEMETRY_VARIANT_MOVE_ASSIGNMENT @@ -636,24 +638,24 @@ template class copy_assignment; #define OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ - template \ - class copy_assignment, copy_assignable_trait> \ - : public move_assignment> \ - { \ - using super = move_assignment>; \ - \ - public: \ - using super::super; \ - using super::operator=; \ - \ - copy_assignment(const copy_assignment &) = default; \ - copy_assignment(copy_assignment &&) = default; \ - ~copy_assignment() = default; \ - definition copy_assignment &operator=(copy_assignment &&) = default; \ + template \ + class copy_assignment, copy_assignable_trait> \ + : public move_assignment> \ + { \ + using super = move_assignment>; \ + \ + public: \ + using super::super; \ + using super::operator=; \ + \ + copy_assignment(const copy_assignment &) = default; \ + copy_assignment(copy_assignment &&) = default; \ + ~copy_assignment() = default; \ + definition copy_assignment &operator=(copy_assignment &&) = default; \ } -OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable, - copy_assignment &operator=(const copy_assignment &that) = default;); +OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT( + Trait::TriviallyAvailable, copy_assignment &operator=(const copy_assignment &that) = default;); OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT( Trait::Available, @@ -663,8 +665,8 @@ OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT( return *this; }); -OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable, - copy_assignment &operator=(const copy_assignment &) = delete;); +OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT( + Trait::Unavailable, copy_assignment &operator=(const copy_assignment &) = delete;); #undef OPENTELEMETRY_VARIANT_COPY_ASSIGNMENT template diff --git a/api/test/nostd/utility_test.cc b/api/test/nostd/utility_test.cc index 3e924bc4c7..ee38f3f474 100644 --- a/api/test/nostd/utility_test.cc +++ b/api/test/nostd/utility_test.cc @@ -40,7 +40,8 @@ TEST(UtilityTest, Size) EXPECT_FALSE(decltype(IsSizeCallable(x)){}); } -TEST(UtilityTest, MakeIndexSequence) { +TEST(UtilityTest, MakeIndexSequence) +{ EXPECT_TRUE((std::is_same, opentelemetry::nostd::index_sequence<>>::value)); EXPECT_TRUE((std::is_same, diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index e0c4e481e8..6b09f351fe 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -1,7 +1,7 @@ #include "opentelemetry/nostd/variant.h" -#include #include +#include #include @@ -35,12 +35,14 @@ TEST(VariantSizeTest, GetVariantSize) TEST(VariantAlternativeTest, GetVariantSize) { EXPECT_TRUE((std::is_same>, int>::value)); - EXPECT_TRUE((std::is_same>, double>::value)); EXPECT_TRUE( - (std::is_same>, const double>::value)); + (std::is_same>, double>::value)); + EXPECT_TRUE((std::is_same>, + const double>::value)); } -TEST(VariantTest, Get) { +TEST(VariantTest, Get) +{ nostd::variant v, w; v = 12; EXPECT_EQ(nostd::get(v), 12); @@ -56,7 +58,8 @@ TEST(VariantTest, Get) { #endif } -TEST(VariantTest, Comparison) { +TEST(VariantTest, Comparison) +{ nostd::variant v, w; EXPECT_TRUE(v == w); EXPECT_FALSE(v != w); @@ -65,9 +68,11 @@ TEST(VariantTest, Comparison) { EXPECT_FALSE(v == w); } -TEST(VariantTest, Visit) { +TEST(VariantTest, Visit) +{ nostd::variant v; - struct { + struct + { int operator()(int) { return 0; } int operator()(float) { return 1; } } a; @@ -76,11 +81,12 @@ TEST(VariantTest, Visit) { EXPECT_EQ(nostd::visit(a, v), 1); } -TEST(VariantTest, Destructor) { +TEST(VariantTest, Destructor) +{ nostd::variant v; int destroy_count = 0; - v = DestroyCounter{&destroy_count}; - destroy_count = 0; - v = 1; + v = DestroyCounter{&destroy_count}; + destroy_count = 0; + v = 1; EXPECT_EQ(destroy_count, 1); } From 73e5a44276bda37cf058d74694d67450c6cc9687 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 12:09:26 -0700 Subject: [PATCH 19/42] Add copyrights --- .../opentelemetry/nostd/detail/find_index.h | 8 +++++++ .../nostd/detail/recursive_union.h | 8 +++++++ api/include/opentelemetry/nostd/variant.h | 8 +++++++ third_party/boost/LICENSE.md | 23 +++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 third_party/boost/LICENSE.md diff --git a/api/include/opentelemetry/nostd/detail/find_index.h b/api/include/opentelemetry/nostd/detail/find_index.h index 20d2c64a4e..130bc21db4 100644 --- a/api/include/opentelemetry/nostd/detail/find_index.h +++ b/api/include/opentelemetry/nostd/detail/find_index.h @@ -1,3 +1,11 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// Copyright OpenTelemetry Authors, 2020 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file third_party/boost/LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + #pragma once #include diff --git a/api/include/opentelemetry/nostd/detail/recursive_union.h b/api/include/opentelemetry/nostd/detail/recursive_union.h index c03cf4cd23..8de72592f5 100644 --- a/api/include/opentelemetry/nostd/detail/recursive_union.h +++ b/api/include/opentelemetry/nostd/detail/recursive_union.h @@ -1,3 +1,11 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// Copyright OpenTelemetry Authors, 2020 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file third_party/boost/LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + #pragma once #include diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 86f734c572..817d52ae7e 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -1,3 +1,11 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// Copyright OpenTelemetry Authors, 2020 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file third_party/boost/LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + #pragma once #include diff --git a/third_party/boost/LICENSE.md b/third_party/boost/LICENSE.md new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/third_party/boost/LICENSE.md @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. From 6382f42d3b0d88c57a487df113cf5ed67ab005ec Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 12:27:32 -0700 Subject: [PATCH 20/42] Add more variant tests --- api/test/nostd/variant_test.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 6b09f351fe..110271e5cf 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -66,6 +66,12 @@ TEST(VariantTest, Comparison) v = 3.0f; EXPECT_TRUE(v != w); EXPECT_FALSE(v == w); + v = 2; + w = 3; + EXPECT_TRUE(v != w); + EXPECT_FALSE(v == w); + EXPECT_TRUE(v < w); + EXPECT_FALSE(v > w); } TEST(VariantTest, Visit) @@ -89,4 +95,10 @@ TEST(VariantTest, Destructor) destroy_count = 0; v = 1; EXPECT_EQ(destroy_count, 1); + { + nostd::variant w; + w = DestroyCounter{&destroy_count}; + destroy_count = 0; + } + EXPECT_EQ(destroy_count, 1); } From 9ecdcda96a85dfab14a1da405e81be1f955e7bae Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 12:37:41 -0700 Subject: [PATCH 21/42] Reformat --- api/include/opentelemetry/nostd/variant.h | 91 +++++++++++------------ api/test/nostd/variant_test.cc | 2 +- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 817d52ae7e..912c985cfc 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -26,11 +26,9 @@ #include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" -#define AUTO auto #define AUTO_RETURN(...) \ ->decay_t { return __VA_ARGS__; } -#define AUTO_REFREF auto #define AUTO_REFREF_RETURN(...) \ ->decltype((__VA_ARGS__)) \ { \ @@ -38,7 +36,6 @@ return __VA_ARGS__; \ } -#define DECLTYPE_AUTO auto #define DECLTYPE_AUTO_RETURN(...) \ ->decltype(__VA_ARGS__) { return __VA_ARGS__; } @@ -69,7 +66,7 @@ namespace access struct base { template - inline static constexpr AUTO_REFREF get_alt(V &&v) + inline static constexpr auto get_alt(V &&v) #ifdef _MSC_VER AUTO_REFREF_RETURN(recursive_union::get_alt(std::forward(v).data_, in_place_index_t{})) #else @@ -80,7 +77,7 @@ struct base struct variant { template - inline static constexpr AUTO_REFREF get_alt(V &&v) + inline static constexpr auto get_alt(V &&v) AUTO_REFREF_RETURN(base::get_alt(std::forward(v).impl_)) }; } // namespace access @@ -114,7 +111,7 @@ struct base "`visit` requires the visitor to have a single return type"); template - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Alts &&... alts) + inline static constexpr auto invoke(Visitor &&visitor, Alts &&... alts) DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), std::forward(alts)...)) }; @@ -159,19 +156,19 @@ struct base template struct impl> { - inline constexpr AUTO operator()() const AUTO_RETURN(&dispatch) + inline constexpr auto operator()() const AUTO_RETURN(&dispatch) }; template struct impl, Ls...> { - inline constexpr AUTO operator()() const + inline constexpr auto operator()() const AUTO_RETURN(make_farray(impl, Ls...>{}()...)) }; }; template - inline static constexpr AUTO make_fmatrix() AUTO_RETURN( + inline static constexpr auto make_fmatrix() AUTO_RETURN( typename make_fmatrix_impl:: template impl, make_index_sequence::size()>...>{}()) @@ -189,7 +186,7 @@ struct base } template - inline static constexpr AUTO impl(index_sequence) + inline static constexpr auto impl(index_sequence) AUTO_RETURN(make_farray(&dispatch...)) }; @@ -232,16 +229,15 @@ constexpr fdiagonal_t fdiagonal::value; struct alt { template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) - DECLTYPE_AUTO_RETURN( - base::at(base::make_fmatrix(vs)))...>(), - vs.index()...)(std::forward(visitor), as_base(std::forward(vs))...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( - base::at(base::make_fdiagonal(vs)))...>(), - index)(std::forward(visitor), as_base(std::forward(vs))...)) + inline static constexpr auto visit_alt(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( + base::at(base::make_fmatrix(vs)))...>(), + vs.index()...)(std::forward(visitor), as_base(std::forward(vs))...)) + + template + inline static constexpr auto visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN(base::at( + base::make_fdiagonal(vs)))...>(), + index)(std::forward(visitor), as_base(std::forward(vs))...)) }; struct variant @@ -263,7 +259,7 @@ struct variant static_assert(visitor::template does_not_handle(), "`visit` requires the visitor to be exhaustive."); - inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor, Values &&... values) + inline static constexpr auto invoke(Visitor &&visitor, Values &&... values) DECLTYPE_AUTO_RETURN(nostd::invoke(std::forward(visitor), std::forward(values)...)) }; @@ -274,38 +270,44 @@ struct variant Visitor &&visitor_; template - inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const DECLTYPE_AUTO_RETURN( + inline constexpr auto operator()(Alts &&... alts) const DECLTYPE_AUTO_RETURN( visit_exhaustiveness_check(alts).value))...>::invoke( std::forward(visitor_), std::forward(alts).value...)) }; template - inline static constexpr AUTO make_value_visitor(Visitor &&visitor) + inline static constexpr auto make_value_visitor(Visitor &&visitor) AUTO_RETURN(value_visitor{std::forward(visitor)}) public : template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, Vs &&... vs) + inline static constexpr auto visit_alt(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN(alt::visit_alt(std::forward(visitor), std::forward(vs).impl_...)) template - inline static constexpr DECLTYPE_AUTO - visit_alt_at(std::size_t index, Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( - alt::visit_alt_at(index, std::forward(visitor), std::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, Vs &&... vs) - DECLTYPE_AUTO_RETURN(visit_alt(make_value_visitor(std::forward(visitor)), - std::forward(vs)...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_value_at(std::size_t index, Visitor &&visitor, Vs &&... vs) - DECLTYPE_AUTO_RETURN(visit_alt_at(index, - make_value_visitor(std::forward(visitor)), - std::forward(vs)...)) + inline static constexpr auto visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(alt::visit_alt_at(index, + std::forward(visitor), + std::forward(vs).impl_...)) + + template + inline static constexpr auto visit_value(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt(make_value_visitor(std::forward(visitor)), + std::forward(vs)...)) + + template + inline static constexpr auto visit_value_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(visit_alt_at( + index, + make_value_visitor(std::forward(visitor)), + std::forward(vs)...)) }; } // namespace visitation @@ -1033,12 +1035,12 @@ struct generic_get_impl { constexpr generic_get_impl(int) noexcept {} - constexpr AUTO_REFREF operator()(V &&v) const + constexpr auto operator()(V &&v) const AUTO_REFREF_RETURN(access::variant::get_alt(std::forward(v)).value) }; template -inline constexpr AUTO_REFREF generic_get(V &&v) AUTO_REFREF_RETURN(generic_get_impl( +inline constexpr auto generic_get(V &&v) AUTO_REFREF_RETURN(generic_get_impl( holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))(std::forward(v))) } // namespace detail @@ -1094,7 +1096,7 @@ namespace detail { template -inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept AUTO_RETURN( +inline constexpr /* auto * */ auto generic_get_if(V *v) noexcept AUTO_RETURN( v &&holds_alternative(*v) ? std::addressof(access::variant::get_alt(*v).value) : nullptr) } // namespace detail @@ -1256,7 +1258,7 @@ inline constexpr bool all_of(const std::array &bs) } // namespace detail template -inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( +inline constexpr auto visit(Visitor &&visitor, Vs &&... vs) DECLTYPE_AUTO_RETURN( (detail::all_of(std::array{{!vs.valueless_by_exception()...}}) ? (void)0 : throw_bad_variant_access()), @@ -1270,11 +1272,8 @@ inline auto swap(variant &lhs, variant &rhs) noexcept(noexcept(lhs } // namespace nostd OPENTELEMETRY_END_NAMESPACE -#undef AUTO #undef AUTO_RETURN -#undef AUTO_REFREF #undef AUTO_REFREF_RETURN -#undef DECLTYPE_AUTO #undef DECLTYPE_AUTO_RETURN diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 110271e5cf..5ebc1f8106 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -97,7 +97,7 @@ TEST(VariantTest, Destructor) EXPECT_EQ(destroy_count, 1); { nostd::variant w; - w = DestroyCounter{&destroy_count}; + w = DestroyCounter{&destroy_count}; destroy_count = 0; } EXPECT_EQ(destroy_count, 1); From 18761c6e7220233841386cb3f0ed93a8b7b5f9be Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 12:42:56 -0700 Subject: [PATCH 22/42] Add more tests --- api/test/nostd/variant_test.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/api/test/nostd/variant_test.cc b/api/test/nostd/variant_test.cc index 5ebc1f8106..b05f805e06 100644 --- a/api/test/nostd/variant_test.cc +++ b/api/test/nostd/variant_test.cc @@ -102,3 +102,15 @@ TEST(VariantTest, Destructor) } EXPECT_EQ(destroy_count, 1); } + +TEST(VariantTest, Conversion) +{ + nostd::variant x("abc"); + x = "def"; + EXPECT_EQ(nostd::get(x), "def"); + + nostd::variant y("abc"); + EXPECT_TRUE(nostd::holds_alternative(y)); + y = std::string{"xyz"}; + EXPECT_TRUE(nostd::holds_alternative(y)); +} From a77ca9aac91de5aeb2078c8ef2924b3a4d536ce3 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 3 Apr 2020 13:48:07 -0700 Subject: [PATCH 23/42] Fix for gcc-4.8 --- api/include/opentelemetry/config.h | 9 +++++ .../opentelemetry/nostd/detail/trait.h | 13 ++++--- api/include/opentelemetry/nostd/type_traits.h | 39 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 api/include/opentelemetry/config.h diff --git a/api/include/opentelemetry/config.h b/api/include/opentelemetry/config.h new file mode 100644 index 0000000000..1718c417b7 --- /dev/null +++ b/api/include/opentelemetry/config.h @@ -0,0 +1,9 @@ +#pragma once + +#ifndef __has_include +# define __has_include(x) 0 +#endif + +#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 +# define OPENTELEMETRY_TRIVIALITY_TYPE_TRAITS +#endif diff --git a/api/include/opentelemetry/nostd/detail/trait.h b/api/include/opentelemetry/nostd/detail/trait.h index be2c3f849b..d4ed09cbb5 100644 --- a/api/include/opentelemetry/nostd/detail/trait.h +++ b/api/include/opentelemetry/nostd/detail/trait.h @@ -2,6 +2,7 @@ #include +#include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -49,19 +50,19 @@ inline constexpr Trait common_trait(Traits... ts) template struct traits { - static constexpr Trait copy_constructible_trait = common_trait( - trait()...); + static constexpr Trait copy_constructible_trait = + common_trait(trait()...); - static constexpr Trait move_constructible_trait = common_trait( - trait()...); + static constexpr Trait move_constructible_trait = + common_trait(trait()...); static constexpr Trait copy_assignable_trait = common_trait(copy_constructible_trait, - trait()...); + trait()...); static constexpr Trait move_assignable_trait = common_trait(move_constructible_trait, - trait()...); + trait()...); static constexpr Trait destructible_trait = common_trait(trait()...); diff --git a/api/include/opentelemetry/nostd/type_traits.h b/api/include/opentelemetry/nostd/type_traits.h index 2fa9483d07..a42f440df8 100644 --- a/api/include/opentelemetry/nostd/type_traits.h +++ b/api/include/opentelemetry/nostd/type_traits.h @@ -3,6 +3,7 @@ #include #include +#include "opentelemetry/config.h" #include "opentelemetry/nostd/detail/void.h" #include "opentelemetry/version.h" @@ -107,5 +108,43 @@ struct is_nothrow_swappable : std::false_type } // namespace detail template using is_nothrow_swappable = detail::swappable::is_nothrow_swappable::value, T>; + +/** + * Back port of + * std::is_trivialy_copy_constructible + * std::is_trivialy_move_constructible + * std::is_trivialy_copy_assignable + * std::is_trivialy_move_assignable + */ +#ifdef OPENTELEMETRY_TRIVIALITY_TYPE_TRAITS +using std::is_trivially_copy_assignable; +using std::is_trivially_copy_constructible; +using std::is_trivially_move_assignable; +using std::is_trivially_move_constructible; +#else +template +struct is_trivially_copy_constructible +{ + static constexpr bool value = std::is_copy_constructible::value && __has_trivial_copy(T); +}; + +template +struct is_trivially_move_constructible +{ + static constexpr bool value = __is_trivial(T); +}; + +template +struct is_trivially_copy_assignable +{ + static constexpr bool value = std::is_copy_assignable::value && __has_trivial_assign(T); +}; + +template +struct is_trivially_move_assignable +{ + static constexpr bool value = __is_trivial(T); +}; +#endif } // namespace nostd OPENTELEMETRY_END_NAMESPACE From 7d81a523370862e646ccf527cb7726e3b8ad4174 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 22:06:55 -0700 Subject: [PATCH 24/42] Add AttributeValue --- .../opentelemetry/nostd/function_ref.h | 81 +++++++++++++++++++ .../opentelemetry/trace/attribute_value.h | 22 +++++ .../opentelemetry/trace/key_value_iterable.h | 20 +++++ .../trace/key_value_iterable_view.h | 62 ++++++++++++++ api/test/trace/BUILD | 11 +++ .../trace/key_value_iterable_view_test.cc | 64 +++++++++++++++ 6 files changed, 260 insertions(+) create mode 100644 api/include/opentelemetry/nostd/function_ref.h create mode 100644 api/include/opentelemetry/trace/attribute_value.h create mode 100644 api/include/opentelemetry/trace/key_value_iterable.h create mode 100644 api/include/opentelemetry/trace/key_value_iterable_view.h create mode 100644 api/test/trace/key_value_iterable_view_test.cc diff --git a/api/include/opentelemetry/nostd/function_ref.h b/api/include/opentelemetry/nostd/function_ref.h new file mode 100644 index 0000000000..0355fa8f74 --- /dev/null +++ b/api/include/opentelemetry/nostd/function_ref.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace nostd +{ +template +class function_ref; + +/** + * Non-owning function reference that can be used as a more performant + * replacement for std::function when ownership sematics aren't needed. + * + * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0792r0.html + * + * Based off of https://stackoverflow.com/a/39087660/4447365 + */ +template +class function_ref { + void* callable_ = nullptr; + R (*invoker_)(void*, Args...) = nullptr; + + template + using FunctionPointer = decltype(std::addressof(std::declval())); + + template + void BindTo(F& f) noexcept { + callable_ = static_cast(std::addressof(f)); + invoker_ = [](void* callable_, Args... args) -> R { + return (*static_cast>(callable_))( + std::forward(args)...); + }; + } + + template + void BindTo(R_in (*f)(Args_in...)) noexcept { + using F = decltype(f); + if (f == nullptr) { + return BindTo(nullptr); + } + callable_ = reinterpret_cast(f); + invoker_ = [](void* callable_, Args... args) -> R { + return (F(callable_))(std::forward(args)...); + }; + } + + void BindTo(std::nullptr_t) noexcept { + callable_ = nullptr; + invoker_ = nullptr; + } + + public: + template < + class F, + typename std::enable_if< + !std::is_same::type>{}, + int>::type = 0, + typename std::enable_if< + std::is_convertible::type, R>{}, + int>::type = 0> + function_ref(F&& f) { + BindTo(f); // not forward + } + + function_ref(std::nullptr_t) {} + + function_ref(const function_ref&) noexcept = default; + function_ref(function_ref&&) noexcept = default; + + R operator()(Args... args) const { + return invoker_(callable_, std::forward(args)...); + } + + explicit operator bool() const { return invoker_; } +}; +} // namespace nostd +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/trace/attribute_value.h new file mode 100644 index 0000000000..a8aa6e41ca --- /dev/null +++ b/api/include/opentelemetry/trace/attribute_value.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "opentelemetry/nostd/variant.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +using AttributeValue = nostd::variant< + bool, + int, + int64_t, + unsigned int, + uint64_t, + double, + nostd::string_view +>; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable.h b/api/include/opentelemetry/trace/key_value_iterable.h new file mode 100644 index 0000000000..b2bdb2d7ee --- /dev/null +++ b/api/include/opentelemetry/trace/key_value_iterable.h @@ -0,0 +1,20 @@ +#pragma once + +#include "opentelemetry/nostd/function_ref.h" +#include "opentelemetry/trace/attribute_value.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +class KeyValueIterable { + public: + virtual ~KeyValueIterable() = default; + + virtual bool ForEachKeyValue( + nostd::function_ref callback) const noexcept = 0; + + virtual size_t size() const noexcept = 0; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h new file mode 100644 index 0000000000..ff65033cad --- /dev/null +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include + +#include "opentelemetry/nostd/utility.h" +#include "opentelemetry/trace/key_value_iterable.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace detail +{ +template +auto is_key_value_iterable_impl(T iterable) + -> decltype(std::pair(std::begin(iterable)->first, + std::begin(iterable)->second), + nostd::size(iterable), + std::true_type{}); + +std::false_type is_key_value_iterable_impl(...); + +template +struct is_key_value_iterable +{ + static const bool value = decltype(detail::is_key_value_iterable_impl(std::declval()))::value; +}; +} // namespace detail + +template +class KeyValueIterableView final : public KeyValueIterable +{ + static_assert(detail::is_key_value_iterable::value, "Must be a key-value iterable"); +public: + KeyValueIterableView(const T &container) noexcept : container_{&container} + {} + + // KeyValueIterable + bool ForEachKeyValue(nostd::function_ref callback) const + noexcept override + { + auto iter = std::begin(*container_); + auto last = std::end(*container_); + for (; iter != last; ++iter) + { + if (!callback(iter->first, iter->second)) + { + return false; + } + } + return true; + } + + size_t size() const noexcept override { return nostd::size(*container_); } + +private: + const T* container_; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/trace/BUILD b/api/test/trace/BUILD index d4a9ddb8cb..ed3d584712 100644 --- a/api/test/trace/BUILD +++ b/api/test/trace/BUILD @@ -1,5 +1,16 @@ load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") +cc_test( + name = "key_value_iterable_view_test", + srcs = [ + "key_value_iterable_view_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "noop_test", srcs = [ diff --git a/api/test/trace/key_value_iterable_view_test.cc b/api/test/trace/key_value_iterable_view_test.cc new file mode 100644 index 0000000000..8641ac8abe --- /dev/null +++ b/api/test/trace/key_value_iterable_view_test.cc @@ -0,0 +1,64 @@ +#include "opentelemetry/trace/key_value_iterable_view.h" + +#include + +#include + +using namespace opentelemetry; + +static std::map TakeKeyValues( + const trace::KeyValueIterable &iterable) +{ + std::map result; + iterable.ForEachKeyValue([&](nostd::string_view key, trace::AttributeValue value) noexcept { + result.emplace(key, value); + return true; + }); + return result; +} + +template ::value> * = nullptr> +static std::map TakeKeyValues(const T &iterable) +{ + return TakeKeyValues(trace::KeyValueIterableView{iterable}); +} + +TEST(KeyValueIterableViewTest, is_key_value_iterable) { + using M1 = std::map; + EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); + + using M2 = std::map; + EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); + + using M3 = std::map; + EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); + + struct A {}; + using M4 = std::map; + EXPECT_FALSE(bool{trace::detail::is_key_value_iterable::value}); +} + +TEST(KeyValueIterableViewTest, ForEachKeyValue) { + std::map m1 = {{"abc", "123"}, {"xyz", "456"}}; + EXPECT_EQ(TakeKeyValues(m1), + (std::map{{"abc", "123"}, {"xyz", "456"}})); + + std::vector> v1 = {{"abc", 123}, {"xyz", 456}}; + EXPECT_EQ(TakeKeyValues(v1), + (std::map{{"abc", 123}, {"xyz", 456}})); +} + +TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) { + using M = std::map; + M m1 = {{"abc", "123"}, {"xyz", "456"}}; + trace::KeyValueIterableView iterable{m1}; + int count = 0; + auto exit = iterable.ForEachKeyValue([&count](nostd::string_view /*key*/, + trace::AttributeValue /*value*/) noexcept { + ++count; + return false; + }); + EXPECT_EQ(count, 1); + EXPECT_FALSE(exit); +} From bb7147d73c08d02f6dadc3d1a089d059682bce2e Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 22:37:40 -0700 Subject: [PATCH 25/42] Support passing attributes in AddEvents api --- api/include/opentelemetry/plugin/tracer.h | 7 ++++ api/include/opentelemetry/trace/noop.h | 13 +++++--- api/include/opentelemetry/trace/span.h | 39 +++++++++++++++++++++++ examples/plugin/plugin/tracer.cc | 5 +++ sdk/src/trace/span.cc | 9 ++++++ sdk/src/trace/span.h | 4 +++ 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/api/include/opentelemetry/plugin/tracer.h b/api/include/opentelemetry/plugin/tracer.h index 0e44d6c71a..b2199a07bf 100644 --- a/api/include/opentelemetry/plugin/tracer.h +++ b/api/include/opentelemetry/plugin/tracer.h @@ -25,6 +25,13 @@ class Span final : public trace::Span span_->AddEvent(name, timestamp); } + void AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const trace::KeyValueIterable &attributes) noexcept override + { + span_->AddEvent(name, timestamp, attributes); + } + void SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept override { span_->SetStatus(code, description); diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index 63335867c2..336b28d902 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -24,13 +24,18 @@ class NoopSpan final : public Span public: explicit NoopSpan(const std::shared_ptr &tracer) noexcept : tracer_{tracer} {} - void AddEvent(nostd::string_view name) noexcept override {} + void AddEvent(nostd::string_view /*name*/) noexcept override {} - void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept override {} + void AddEvent(nostd::string_view /*name*/, core::SystemTimestamp /*timestamp*/) noexcept override + {} + + void AddEvent(nostd::string_view /*name*/, + core::SystemTimestamp /*timestamp*/, + const trace::KeyValueIterable &/*attributes*/) noexcept override {} - void SetStatus(CanonicalCode code, nostd::string_view description) noexcept override {} + void SetStatus(CanonicalCode /*code*/, nostd::string_view /*description*/) noexcept override {} - void UpdateName(nostd::string_view name) noexcept override {} + void UpdateName(nostd::string_view /*name*/) noexcept override {} void End() noexcept override {} diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index bed9e55afe..e9790c0fa4 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -4,7 +4,9 @@ #include "opentelemetry/core/timestamp.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/span.h" #include "opentelemetry/trace/canonical_code.h" +#include "opentelemetry/trace/key_value_iterable_view.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -82,6 +84,43 @@ class Span // virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp // timestamp, nostd::span> attributes) noexcept = 0; + virtual void AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const KeyValueIterable &attributes) noexcept = 0; + + template ::value> * = nullptr> + void AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const T &attributes) noexcept + { + this->AddEvent(name, timestamp, KeyValueIterableView{attributes}); + } + + template ::value> * = nullptr> + void AddEvent(nostd::string_view name, + const T &attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), KeyValueIterableView{attributes}); + } + + void AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + std::initializer_list> + attributes) noexcept + { + this->AddEvent(name, timestamp, + nostd::span>{ + attributes.begin(), attributes.end()}); + } + + void AddEvent(nostd::string_view name, + std::initializer_list> + attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), + nostd::span>{ + attributes.begin(), attributes.end()}); + } // Sets the status of the span. The default status is OK. Only the value of the last call will be // recorded, and implementations are free to ignore previous calls. diff --git a/examples/plugin/plugin/tracer.cc b/examples/plugin/plugin/tracer.cc index 5a0c861ea6..6cf63af118 100644 --- a/examples/plugin/plugin/tracer.cc +++ b/examples/plugin/plugin/tracer.cc @@ -27,6 +27,11 @@ class Span final : public trace::Span void AddEvent(nostd::string_view /*name*/, core::SystemTimestamp /*timestamp*/) noexcept override {} + void AddEvent(nostd::string_view /*name*/, + core::SystemTimestamp /*timestamp*/, + const trace::KeyValueIterable & /*attributes*/) noexcept override + {} + void SetStatus(trace::CanonicalCode /*code*/, nostd::string_view /*description*/) noexcept override {} diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index 54fde5d81d..e8c8764784 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -36,6 +36,15 @@ void Span::AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) no (void)timestamp; } +void Span::AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const trace_api::KeyValueIterable &attributes) noexcept +{ + (void)name; + (void)timestamp; + (void)attributes; +} + void Span::SetStatus(trace_api::CanonicalCode code, nostd::string_view description) noexcept { std::lock_guard lock_guard{mu_}; diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index f4f924aa33..56c499e894 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -26,6 +26,10 @@ class Span final : public trace_api::Span void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept override; + void AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const trace_api::KeyValueIterable &attributes) noexcept override; + void SetStatus(trace_api::CanonicalCode code, nostd::string_view description) noexcept override; void UpdateName(nostd::string_view name) noexcept override; From f61290f60d8b9b7ac59938089a78ffe01549cef5 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 22:43:33 -0700 Subject: [PATCH 26/42] Support passing attributes in AddEvent api --- api/test/trace/noop_test.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/test/trace/noop_test.cc b/api/test/trace/noop_test.cc index cd8cdb6a4b..7d6ed7b742 100644 --- a/api/test/trace/noop_test.cc +++ b/api/test/trace/noop_test.cc @@ -1,6 +1,8 @@ #include "opentelemetry/trace/noop.h" #include +#include +#include #include @@ -12,4 +14,12 @@ TEST(NoopTest, UseNoopTracers) std::shared_ptr tracer{new NoopTracer{}}; auto s1 = tracer->StartSpan("abc"); EXPECT_EQ(&s1->tracer(), tracer.get()); + + std::map attributes1; + s1->AddEvent("abc", attributes1); + + std::vector> attributes2; + s1->AddEvent("abc", attributes2); + + s1->AddEvent("abc", {{"a", 1}, {"b", "2"}, {"c", 3.0}}); } From 92da4a88976d55c061b031705a48bba5f31ad9ec Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 22:44:25 -0700 Subject: [PATCH 27/42] Reformat --- .../opentelemetry/nostd/function_ref.h | 57 ++++++++++--------- .../opentelemetry/trace/attribute_value.h | 13 +---- .../opentelemetry/trace/key_value_iterable.h | 13 +++-- .../trace/key_value_iterable_view.h | 6 +- api/include/opentelemetry/trace/noop.h | 3 +- api/include/opentelemetry/trace/span.h | 5 +- .../trace/key_value_iterable_view_test.cc | 17 +++--- api/test/trace/noop_test.cc | 2 +- 8 files changed, 57 insertions(+), 59 deletions(-) diff --git a/api/include/opentelemetry/nostd/function_ref.h b/api/include/opentelemetry/nostd/function_ref.h index 0355fa8f74..995164df5e 100644 --- a/api/include/opentelemetry/nostd/function_ref.h +++ b/api/include/opentelemetry/nostd/function_ref.h @@ -20,60 +20,61 @@ class function_ref; * Based off of https://stackoverflow.com/a/39087660/4447365 */ template -class function_ref { - void* callable_ = nullptr; - R (*invoker_)(void*, Args...) = nullptr; +class function_ref +{ + void *callable_ = nullptr; + R (*invoker_)(void *, Args...) = nullptr; template - using FunctionPointer = decltype(std::addressof(std::declval())); + using FunctionPointer = decltype(std::addressof(std::declval())); template - void BindTo(F& f) noexcept { - callable_ = static_cast(std::addressof(f)); - invoker_ = [](void* callable_, Args... args) -> R { - return (*static_cast>(callable_))( - std::forward(args)...); + void BindTo(F &f) noexcept + { + callable_ = static_cast(std::addressof(f)); + invoker_ = [](void *callable_, Args... args) -> R { + return (*static_cast>(callable_))(std::forward(args)...); }; } template - void BindTo(R_in (*f)(Args_in...)) noexcept { + void BindTo(R_in (*f)(Args_in...)) noexcept + { using F = decltype(f); - if (f == nullptr) { + if (f == nullptr) + { return BindTo(nullptr); } - callable_ = reinterpret_cast(f); - invoker_ = [](void* callable_, Args... args) -> R { + callable_ = reinterpret_cast(f); + invoker_ = [](void *callable_, Args... args) -> R { return (F(callable_))(std::forward(args)...); }; } - void BindTo(std::nullptr_t) noexcept { + void BindTo(std::nullptr_t) noexcept + { callable_ = nullptr; - invoker_ = nullptr; + invoker_ = nullptr; } - public: +public: template < class F, - typename std::enable_if< - !std::is_same::type>{}, - int>::type = 0, - typename std::enable_if< - std::is_convertible::type, R>{}, - int>::type = 0> - function_ref(F&& f) { + typename std::enable_if::type>{}, + int>::type = 0, + typename std::enable_if::type, R>{}, + int>::type = 0> + function_ref(F &&f) + { BindTo(f); // not forward } function_ref(std::nullptr_t) {} - function_ref(const function_ref&) noexcept = default; - function_ref(function_ref&&) noexcept = default; + function_ref(const function_ref &) noexcept = default; + function_ref(function_ref &&) noexcept = default; - R operator()(Args... args) const { - return invoker_(callable_, std::forward(args)...); - } + R operator()(Args... args) const { return invoker_(callable_, std::forward(args)...); } explicit operator bool() const { return invoker_; } }; diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/trace/attribute_value.h index a8aa6e41ca..a9756123c9 100644 --- a/api/include/opentelemetry/trace/attribute_value.h +++ b/api/include/opentelemetry/trace/attribute_value.h @@ -2,21 +2,14 @@ #include -#include "opentelemetry/nostd/variant.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/variant.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { -using AttributeValue = nostd::variant< - bool, - int, - int64_t, - unsigned int, - uint64_t, - double, - nostd::string_view ->; +using AttributeValue = + nostd::variant; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable.h b/api/include/opentelemetry/trace/key_value_iterable.h index b2bdb2d7ee..a7096cb745 100644 --- a/api/include/opentelemetry/trace/key_value_iterable.h +++ b/api/include/opentelemetry/trace/key_value_iterable.h @@ -7,14 +7,15 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { -class KeyValueIterable { - public: - virtual ~KeyValueIterable() = default; +class KeyValueIterable +{ +public: + virtual ~KeyValueIterable() = default; - virtual bool ForEachKeyValue( - nostd::function_ref callback) const noexcept = 0; + virtual bool ForEachKeyValue( + nostd::function_ref callback) const noexcept = 0; - virtual size_t size() const noexcept = 0; + virtual size_t size() const noexcept = 0; }; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h index ff65033cad..fec77753c7 100644 --- a/api/include/opentelemetry/trace/key_value_iterable_view.h +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -33,9 +33,9 @@ template class KeyValueIterableView final : public KeyValueIterable { static_assert(detail::is_key_value_iterable::value, "Must be a key-value iterable"); + public: - KeyValueIterableView(const T &container) noexcept : container_{&container} - {} + KeyValueIterableView(const T &container) noexcept : container_{&container} {} // KeyValueIterable bool ForEachKeyValue(nostd::function_ref callback) const @@ -56,7 +56,7 @@ class KeyValueIterableView final : public KeyValueIterable size_t size() const noexcept override { return nostd::size(*container_); } private: - const T* container_; + const T *container_; }; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index 336b28d902..0c3ef15c69 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -31,7 +31,8 @@ class NoopSpan final : public Span void AddEvent(nostd::string_view /*name*/, core::SystemTimestamp /*timestamp*/, - const trace::KeyValueIterable &/*attributes*/) noexcept override {} + const trace::KeyValueIterable & /*attributes*/) noexcept override + {} void SetStatus(CanonicalCode /*code*/, nostd::string_view /*description*/) noexcept override {} diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index e9790c0fa4..c9f82b3dda 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -3,8 +3,8 @@ #include #include "opentelemetry/core/timestamp.h" -#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/key_value_iterable_view.h" #include "opentelemetry/version.h" @@ -97,8 +97,7 @@ class Span } template ::value> * = nullptr> - void AddEvent(nostd::string_view name, - const T &attributes) noexcept + void AddEvent(nostd::string_view name, const T &attributes) noexcept { this->AddEvent(name, std::chrono::system_clock::now(), KeyValueIterableView{attributes}); } diff --git a/api/test/trace/key_value_iterable_view_test.cc b/api/test/trace/key_value_iterable_view_test.cc index 8641ac8abe..82e379c8a3 100644 --- a/api/test/trace/key_value_iterable_view_test.cc +++ b/api/test/trace/key_value_iterable_view_test.cc @@ -17,14 +17,14 @@ static std::map TakeKeyValues( return result; } -template ::value> * = nullptr> +template ::value> * = nullptr> static std::map TakeKeyValues(const T &iterable) { return TakeKeyValues(trace::KeyValueIterableView{iterable}); } -TEST(KeyValueIterableViewTest, is_key_value_iterable) { +TEST(KeyValueIterableViewTest, is_key_value_iterable) +{ using M1 = std::map; EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); @@ -34,12 +34,14 @@ TEST(KeyValueIterableViewTest, is_key_value_iterable) { using M3 = std::map; EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); - struct A {}; + struct A + {}; using M4 = std::map; EXPECT_FALSE(bool{trace::detail::is_key_value_iterable::value}); } -TEST(KeyValueIterableViewTest, ForEachKeyValue) { +TEST(KeyValueIterableViewTest, ForEachKeyValue) +{ std::map m1 = {{"abc", "123"}, {"xyz", "456"}}; EXPECT_EQ(TakeKeyValues(m1), (std::map{{"abc", "123"}, {"xyz", "456"}})); @@ -49,9 +51,10 @@ TEST(KeyValueIterableViewTest, ForEachKeyValue) { (std::map{{"abc", 123}, {"xyz", 456}})); } -TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) { +TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) +{ using M = std::map; - M m1 = {{"abc", "123"}, {"xyz", "456"}}; + M m1 = {{"abc", "123"}, {"xyz", "456"}}; trace::KeyValueIterableView iterable{m1}; int count = 0; auto exit = iterable.ForEachKeyValue([&count](nostd::string_view /*key*/, diff --git a/api/test/trace/noop_test.cc b/api/test/trace/noop_test.cc index 7d6ed7b742..de5ee63c09 100644 --- a/api/test/trace/noop_test.cc +++ b/api/test/trace/noop_test.cc @@ -1,7 +1,7 @@ #include "opentelemetry/trace/noop.h" -#include #include +#include #include #include From 841d831fd8aa0a2fc6674611feacec0c908704fa Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 22:47:21 -0700 Subject: [PATCH 28/42] Add cmake test --- api/test/trace/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/test/trace/CMakeLists.txt b/api/test/trace/CMakeLists.txt index 5ddf6da857..f722ae4557 100644 --- a/api/test/trace/CMakeLists.txt +++ b/api/test/trace/CMakeLists.txt @@ -1,5 +1,5 @@ -foreach(testname noop_test provider_test span_id_test trace_id_test - trace_flags_test) +foreach(testname key_value_iterable_view_test noop_test provider_test + span_id_test trace_id_test trace_flags_test) add_executable(${testname} "${testname}.cc") target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) From 66228c3b0635cdc50dc765e54aac250c7f34ffdf Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 23:09:27 -0700 Subject: [PATCH 29/42] Tweak function_ref --- api/include/opentelemetry/nostd/function_ref.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/include/opentelemetry/nostd/function_ref.h b/api/include/opentelemetry/nostd/function_ref.h index 995164df5e..c0ed882e45 100644 --- a/api/include/opentelemetry/nostd/function_ref.h +++ b/api/include/opentelemetry/nostd/function_ref.h @@ -60,7 +60,7 @@ class function_ref public: template < class F, - typename std::enable_if::type>{}, + typename std::enable_if::type>::value, int>::type = 0, typename std::enable_if::type, R>{}, int>::type = 0> From f9fabf187564929ab0aa8bdfedf44f90409c45ec Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 6 Apr 2020 23:12:07 -0700 Subject: [PATCH 30/42] Tweak function_ref --- api/include/opentelemetry/nostd/function_ref.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/include/opentelemetry/nostd/function_ref.h b/api/include/opentelemetry/nostd/function_ref.h index c0ed882e45..33c94d00ab 100644 --- a/api/include/opentelemetry/nostd/function_ref.h +++ b/api/include/opentelemetry/nostd/function_ref.h @@ -62,8 +62,9 @@ class function_ref class F, typename std::enable_if::type>::value, int>::type = 0, - typename std::enable_if::type, R>{}, - int>::type = 0> + typename std::enable_if< + std::is_convertible::type, R>::value, + int>::type = 0> function_ref(F &&f) { BindTo(f); // not forward From 0d90ba5bb290083606036150ed31c0b914aec863 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Wed, 8 Apr 2020 21:43:21 -0700 Subject: [PATCH 31/42] Fix for gcc-4.8 --- api/include/opentelemetry/nostd/detail/void.h | 13 +++++++++++-- api/include/opentelemetry/trace/attribute_value.h | 2 +- .../opentelemetry/trace/key_value_iterable_view.h | 10 +++++++--- api/test/trace/key_value_iterable_view_test.cc | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/void.h b/api/include/opentelemetry/nostd/detail/void.h index 63c548fb72..fc66382dac 100644 --- a/api/include/opentelemetry/nostd/detail/void.h +++ b/api/include/opentelemetry/nostd/detail/void.h @@ -5,10 +5,19 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { +namespace detail { +template +struct voider { + using type = void; +}; +} // namespace detail + /** * Back port of std::void_t + * + * Note: voider workaround is required for gcc-4.8 to make SFINAE work */ -template -using void_t = void; +template +using void_t = typename detail::voider::type; } // namespace nostd OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/trace/attribute_value.h index a9756123c9..4aa850e057 100644 --- a/api/include/opentelemetry/trace/attribute_value.h +++ b/api/include/opentelemetry/trace/attribute_value.h @@ -10,6 +10,6 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { using AttributeValue = - nostd::variant; + nostd::variant; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h index fec77753c7..1cc5de62a7 100644 --- a/api/include/opentelemetry/trace/key_value_iterable_view.h +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -13,10 +13,14 @@ namespace trace { namespace detail { +inline void take_key_value(nostd::string_view, AttributeValue) { +} + template auto is_key_value_iterable_impl(T iterable) - -> decltype(std::pair(std::begin(iterable)->first, - std::begin(iterable)->second), + /* -> decltype(std::pair(std::begin(iterable)->first, */ + /* std::begin(iterable)->second), */ + -> decltype(take_key_value(std::begin(iterable)->first, std::begin(iterable)->second), nostd::size(iterable), std::true_type{}); @@ -35,7 +39,7 @@ class KeyValueIterableView final : public KeyValueIterable static_assert(detail::is_key_value_iterable::value, "Must be a key-value iterable"); public: - KeyValueIterableView(const T &container) noexcept : container_{&container} {} + explicit KeyValueIterableView(const T &container) noexcept : container_{&container} {} // KeyValueIterable bool ForEachKeyValue(nostd::function_ref callback) const diff --git a/api/test/trace/key_value_iterable_view_test.cc b/api/test/trace/key_value_iterable_view_test.cc index 82e379c8a3..157ae7d8af 100644 --- a/api/test/trace/key_value_iterable_view_test.cc +++ b/api/test/trace/key_value_iterable_view_test.cc @@ -11,7 +11,7 @@ static std::map TakeKeyValues( { std::map result; iterable.ForEachKeyValue([&](nostd::string_view key, trace::AttributeValue value) noexcept { - result.emplace(key, value); + result.emplace(std::string{key}, value); return true; }); return result; From 273d5b27e1ebd57604f73c209af6f6aa9887689f Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Wed, 8 Apr 2020 21:44:05 -0700 Subject: [PATCH 32/42] Reformat --- api/include/opentelemetry/nostd/detail/void.h | 8 +++++--- api/include/opentelemetry/trace/key_value_iterable_view.h | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/include/opentelemetry/nostd/detail/void.h b/api/include/opentelemetry/nostd/detail/void.h index fc66382dac..e8d4a48c01 100644 --- a/api/include/opentelemetry/nostd/detail/void.h +++ b/api/include/opentelemetry/nostd/detail/void.h @@ -5,12 +5,14 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -namespace detail { +namespace detail +{ template -struct voider { +struct voider +{ using type = void; }; -} // namespace detail +} // namespace detail /** * Back port of std::void_t diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h index 1cc5de62a7..5d8ede504d 100644 --- a/api/include/opentelemetry/trace/key_value_iterable_view.h +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -13,8 +13,7 @@ namespace trace { namespace detail { -inline void take_key_value(nostd::string_view, AttributeValue) { -} +inline void take_key_value(nostd::string_view, AttributeValue) {} template auto is_key_value_iterable_impl(T iterable) From 0389471d2891a97175c858caa31adea1448aeb05 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Wed, 8 Apr 2020 22:20:49 -0700 Subject: [PATCH 33/42] Add function_ref test --- api/test/nostd/BUILD | 11 ++++++++++ api/test/nostd/CMakeLists.txt | 4 ++-- api/test/nostd/function_ref_test.cc | 33 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 api/test/nostd/function_ref_test.cc diff --git a/api/test/nostd/BUILD b/api/test/nostd/BUILD index 8acfb7c709..35306e6a3c 100644 --- a/api/test/nostd/BUILD +++ b/api/test/nostd/BUILD @@ -1,3 +1,14 @@ +cc_test( + name = "function_ref_test", + srcs = [ + "function_ref_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "string_view_test", srcs = [ diff --git a/api/test/nostd/CMakeLists.txt b/api/test/nostd/CMakeLists.txt index 60d833f0cd..fdbf8e7b07 100644 --- a/api/test/nostd/CMakeLists.txt +++ b/api/test/nostd/CMakeLists.txt @@ -1,7 +1,7 @@ include(GoogleTest) -foreach(testname string_view_test unique_ptr_test utility_test span_test - shared_ptr_test) +foreach(testname function_ref_test string_view_test unique_ptr_test + utility_test span_test shared_ptr_test) add_executable(${testname} "${testname}.cc") target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) diff --git a/api/test/nostd/function_ref_test.cc b/api/test/nostd/function_ref_test.cc new file mode 100644 index 0000000000..148d305344 --- /dev/null +++ b/api/test/nostd/function_ref_test.cc @@ -0,0 +1,33 @@ +#include "opentelemetry/nostd/function_ref.h" + +#include +using namespace opentelemetry::nostd; + +int Call(function_ref f) +{ + return f(); +} + +int Return3() +{ + return 3; +} + +TEST(FunctionRefTest, Call) +{ + int x = 9; + + auto f = [&] { return x; }; + EXPECT_EQ(Call(f), 9); + + EXPECT_EQ(Call(Return3), 3); +} + +TEST(FunctionRefTest, BoolConversion) +{ + auto f = [] { return 0; }; + function_ref fref1{nullptr}; + function_ref fref2{f}; + EXPECT_TRUE(!static_cast(fref1)); + EXPECT_TRUE(static_cast(fref2)); +} From 0fcf7c1641ba7065d7cb27fe33de470f55e893a1 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 20 Apr 2020 14:01:52 -0700 Subject: [PATCH 34/42] Support arrays of primitives --- api/include/opentelemetry/nostd/variant.h | 2 +- .../opentelemetry/trace/attribute_value.h | 14 ++++++++++++-- api/test/trace/key_value_iterable_view_test.cc | 16 +++++++--------- api/test/trace/noop_test.cc | 3 +++ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/api/include/opentelemetry/nostd/variant.h b/api/include/opentelemetry/nostd/variant.h index 912c985cfc..48ef7d56e5 100644 --- a/api/include/opentelemetry/nostd/variant.h +++ b/api/include/opentelemetry/nostd/variant.h @@ -1138,7 +1138,7 @@ struct convert_to_bool static_assert(std::is_convertible, bool>::value, "relational operators must return a type" " implicitly convertible to bool"); - return invoke(RelOp{}, std::forward(lhs), std::forward(rhs)); + return nostd::invoke(RelOp{}, std::forward(lhs), std::forward(rhs)); } }; } // namespace detail diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/trace/attribute_value.h index 4aa850e057..07322f7bb4 100644 --- a/api/include/opentelemetry/trace/attribute_value.h +++ b/api/include/opentelemetry/trace/attribute_value.h @@ -2,6 +2,7 @@ #include +#include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/variant.h" #include "opentelemetry/version.h" @@ -9,7 +10,16 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { -using AttributeValue = - nostd::variant; +using AttributeValue = nostd::variant, + nostd::span, + nostd::span, + nostd::span, + nostd::span>; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/trace/key_value_iterable_view_test.cc b/api/test/trace/key_value_iterable_view_test.cc index 157ae7d8af..72aa1d3d9a 100644 --- a/api/test/trace/key_value_iterable_view_test.cc +++ b/api/test/trace/key_value_iterable_view_test.cc @@ -6,19 +6,19 @@ using namespace opentelemetry; -static std::map TakeKeyValues( - const trace::KeyValueIterable &iterable) +static int TakeKeyValues(const trace::KeyValueIterable &iterable) { std::map result; + int count = 0; iterable.ForEachKeyValue([&](nostd::string_view key, trace::AttributeValue value) noexcept { - result.emplace(std::string{key}, value); + ++count; return true; }); - return result; + return count; } template ::value> * = nullptr> -static std::map TakeKeyValues(const T &iterable) +static int TakeKeyValues(const T &iterable) { return TakeKeyValues(trace::KeyValueIterableView{iterable}); } @@ -43,12 +43,10 @@ TEST(KeyValueIterableViewTest, is_key_value_iterable) TEST(KeyValueIterableViewTest, ForEachKeyValue) { std::map m1 = {{"abc", "123"}, {"xyz", "456"}}; - EXPECT_EQ(TakeKeyValues(m1), - (std::map{{"abc", "123"}, {"xyz", "456"}})); + EXPECT_EQ(TakeKeyValues(m1), 2); std::vector> v1 = {{"abc", 123}, {"xyz", 456}}; - EXPECT_EQ(TakeKeyValues(v1), - (std::map{{"abc", 123}, {"xyz", 456}})); + EXPECT_EQ(TakeKeyValues(v1), 2); } TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) diff --git a/api/test/trace/noop_test.cc b/api/test/trace/noop_test.cc index de5ee63c09..6dad65323b 100644 --- a/api/test/trace/noop_test.cc +++ b/api/test/trace/noop_test.cc @@ -22,4 +22,7 @@ TEST(NoopTest, UseNoopTracers) s1->AddEvent("abc", attributes2); s1->AddEvent("abc", {{"a", 1}, {"b", "2"}, {"c", 3.0}}); + + std::vector>> attributes3; + s1->AddEvent("abc", attributes3); } From 48151b1391cb87e3c7b7fe5082423d4263d2dcc6 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Fri, 1 May 2020 13:01:23 -0700 Subject: [PATCH 35/42] Support bool in AttributeValue --- api/include/opentelemetry/trace/attribute_value.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/trace/attribute_value.h index 07322f7bb4..610beac43a 100644 --- a/api/include/opentelemetry/trace/attribute_value.h +++ b/api/include/opentelemetry/trace/attribute_value.h @@ -10,12 +10,14 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { -using AttributeValue = nostd::variant, nostd::span, nostd::span, nostd::span, From 8f0b128f1aff8b8b8662e8d5295892e09cb52850 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 4 May 2020 08:25:38 -0700 Subject: [PATCH 36/42] Add documentation --- api/include/opentelemetry/trace/key_value_iterable.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/api/include/opentelemetry/trace/key_value_iterable.h b/api/include/opentelemetry/trace/key_value_iterable.h index a7096cb745..d819875746 100644 --- a/api/include/opentelemetry/trace/key_value_iterable.h +++ b/api/include/opentelemetry/trace/key_value_iterable.h @@ -7,14 +7,26 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { +/** + * Supports internal iteration over a collection of key-value pairs. + */ class KeyValueIterable { public: virtual ~KeyValueIterable() = default; + /** + * Iterate over key-value pairs + * @param callback a callback to invoke for each key-value. If the callback returns false, + * the iteration is aborted. + * @return true if every key-value pair was iterated over + */ virtual bool ForEachKeyValue( nostd::function_ref callback) const noexcept = 0; + /** + * @return the number of key-value pairs + */ virtual size_t size() const noexcept = 0; }; } // namespace trace From 5338087742d732b812a8359108588052cd6dbc9a Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 4 May 2020 08:44:43 -0700 Subject: [PATCH 37/42] Allow sdk to use different clocks for timestamping --- api/include/opentelemetry/trace/span.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index c9f82b3dda..1583d06ae3 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -79,15 +79,16 @@ class Span // Adds an event to the Span, with a custom timestamp. virtual void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept = 0; - // TODO // Adds an event to the Span, with a custom timestamp, and attributes. - // virtual void AddEvent(nostd::string_view name, core::SteadyTimestamp - // timestamp, nostd::span> attributes) noexcept = 0; virtual void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp, const KeyValueIterable &attributes) noexcept = 0; + virtual void AddEvent(nostd::string_view name, const KeyValueIterable &attributes) noexcept + { + this->AddEvent(name, std::chrono::system_clock::now(), attributes); + } + template ::value> * = nullptr> void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp, @@ -99,7 +100,7 @@ class Span template ::value> * = nullptr> void AddEvent(nostd::string_view name, const T &attributes) noexcept { - this->AddEvent(name, std::chrono::system_clock::now(), KeyValueIterableView{attributes}); + this->AddEvent(name, KeyValueIterableView{attributes}); } void AddEvent(nostd::string_view name, From 9bb44446404d87bfd4b61beaeb0a0bfdd8c4996d Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 4 May 2020 09:01:52 -0700 Subject: [PATCH 38/42] Remove dead code --- api/include/opentelemetry/trace/key_value_iterable_view.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h index 5d8ede504d..cb59f123ed 100644 --- a/api/include/opentelemetry/trace/key_value_iterable_view.h +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -17,8 +17,6 @@ inline void take_key_value(nostd::string_view, AttributeValue) {} template auto is_key_value_iterable_impl(T iterable) - /* -> decltype(std::pair(std::begin(iterable)->first, */ - /* std::begin(iterable)->second), */ -> decltype(take_key_value(std::begin(iterable)->first, std::begin(iterable)->second), nostd::size(iterable), std::true_type{}); From aa3960313c658b67b84fbb26801e5e5a3aadab54 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 4 May 2020 09:21:20 -0700 Subject: [PATCH 39/42] Increase windows ci time limit --- .circleci/config.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e80fa8a739..d65cc6d16b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -123,7 +123,9 @@ jobs: - checkout - run: ./ci/setup_windows_cmake.ps1 - run: ./ci/setup_windows_ci_environment.ps1 - - run: ./ci/install_windows_protobuf.ps1 + - run: + command: ./ci/install_windows_protobuf.ps1 + no_output_timeout: 15m - run: ./ci/do_ci.ps1 cmake.test - run: ./ci/do_ci.sh cmake.exporter.otprotocol.test From fc0e1206cb5c3b9ab7f75540c702a2583bbd956d Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Mon, 4 May 2020 09:36:30 -0700 Subject: [PATCH 40/42] Reformat --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d65cc6d16b..ea4d74a365 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -123,7 +123,7 @@ jobs: - checkout - run: ./ci/setup_windows_cmake.ps1 - run: ./ci/setup_windows_ci_environment.ps1 - - run: + - run: command: ./ci/install_windows_protobuf.ps1 no_output_timeout: 15m - run: ./ci/do_ci.ps1 cmake.test From e92a7c4027f5e1e0f263b0f125f3cf56410beda6 Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Sun, 10 May 2020 16:44:13 -0700 Subject: [PATCH 41/42] Move AttributeValue to common --- .../opentelemetry/{trace => common}/attribute_value.h | 4 ++-- api/include/opentelemetry/trace/key_value_iterable.h | 5 +++-- api/include/opentelemetry/trace/key_value_iterable_view.h | 5 +++-- api/include/opentelemetry/trace/span.h | 8 ++++---- api/test/trace/key_value_iterable_view_test.cc | 8 ++++---- 5 files changed, 16 insertions(+), 14 deletions(-) rename api/include/opentelemetry/{trace => common}/attribute_value.h (96%) diff --git a/api/include/opentelemetry/trace/attribute_value.h b/api/include/opentelemetry/common/attribute_value.h similarity index 96% rename from api/include/opentelemetry/trace/attribute_value.h rename to api/include/opentelemetry/common/attribute_value.h index 610beac43a..4ab6e76aaa 100644 --- a/api/include/opentelemetry/trace/attribute_value.h +++ b/api/include/opentelemetry/common/attribute_value.h @@ -8,7 +8,7 @@ #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE -namespace trace +namespace common { using AttributeValue = nostd::variant, nostd::span, nostd::span>; -} // namespace trace +} // namespace common OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/key_value_iterable.h b/api/include/opentelemetry/trace/key_value_iterable.h index d819875746..8b1f2e1124 100644 --- a/api/include/opentelemetry/trace/key_value_iterable.h +++ b/api/include/opentelemetry/trace/key_value_iterable.h @@ -1,7 +1,7 @@ #pragma once +#include "opentelemetry/common/attribute_value.h" #include "opentelemetry/nostd/function_ref.h" -#include "opentelemetry/trace/attribute_value.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -22,7 +22,8 @@ class KeyValueIterable * @return true if every key-value pair was iterated over */ virtual bool ForEachKeyValue( - nostd::function_ref callback) const noexcept = 0; + nostd::function_ref callback) const + noexcept = 0; /** * @return the number of key-value pairs diff --git a/api/include/opentelemetry/trace/key_value_iterable_view.h b/api/include/opentelemetry/trace/key_value_iterable_view.h index cb59f123ed..2daf83c713 100644 --- a/api/include/opentelemetry/trace/key_value_iterable_view.h +++ b/api/include/opentelemetry/trace/key_value_iterable_view.h @@ -13,7 +13,7 @@ namespace trace { namespace detail { -inline void take_key_value(nostd::string_view, AttributeValue) {} +inline void take_key_value(nostd::string_view, common::AttributeValue) {} template auto is_key_value_iterable_impl(T iterable) @@ -39,7 +39,8 @@ class KeyValueIterableView final : public KeyValueIterable explicit KeyValueIterableView(const T &container) noexcept : container_{&container} {} // KeyValueIterable - bool ForEachKeyValue(nostd::function_ref callback) const + bool ForEachKeyValue( + nostd::function_ref callback) const noexcept override { auto iter = std::begin(*container_); diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 1583d06ae3..7d323b7207 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -105,20 +105,20 @@ class Span void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp, - std::initializer_list> + std::initializer_list> attributes) noexcept { this->AddEvent(name, timestamp, - nostd::span>{ + nostd::span>{ attributes.begin(), attributes.end()}); } void AddEvent(nostd::string_view name, - std::initializer_list> + std::initializer_list> attributes) noexcept { this->AddEvent(name, std::chrono::system_clock::now(), - nostd::span>{ + nostd::span>{ attributes.begin(), attributes.end()}); } diff --git a/api/test/trace/key_value_iterable_view_test.cc b/api/test/trace/key_value_iterable_view_test.cc index 72aa1d3d9a..9c262eb3f1 100644 --- a/api/test/trace/key_value_iterable_view_test.cc +++ b/api/test/trace/key_value_iterable_view_test.cc @@ -8,9 +8,9 @@ using namespace opentelemetry; static int TakeKeyValues(const trace::KeyValueIterable &iterable) { - std::map result; + std::map result; int count = 0; - iterable.ForEachKeyValue([&](nostd::string_view key, trace::AttributeValue value) noexcept { + iterable.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { ++count; return true; }); @@ -31,7 +31,7 @@ TEST(KeyValueIterableViewTest, is_key_value_iterable) using M2 = std::map; EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); - using M3 = std::map; + using M3 = std::map; EXPECT_TRUE(bool{trace::detail::is_key_value_iterable::value}); struct A @@ -56,7 +56,7 @@ TEST(KeyValueIterableViewTest, ForEachKeyValueWithExit) trace::KeyValueIterableView iterable{m1}; int count = 0; auto exit = iterable.ForEachKeyValue([&count](nostd::string_view /*key*/, - trace::AttributeValue /*value*/) noexcept { + common::AttributeValue /*value*/) noexcept { ++count; return false; }); From 92df11e6f9203d7d35dd9ede4c54e0b811277ece Mon Sep 17 00:00:00 2001 From: Ryan Burn Date: Sun, 10 May 2020 16:52:22 -0700 Subject: [PATCH 42/42] Add missing type to AttributeValue --- api/include/opentelemetry/common/attribute_value.h | 1 + 1 file changed, 1 insertion(+) diff --git a/api/include/opentelemetry/common/attribute_value.h b/api/include/opentelemetry/common/attribute_value.h index 4ab6e76aaa..6340a4f97c 100644 --- a/api/include/opentelemetry/common/attribute_value.h +++ b/api/include/opentelemetry/common/attribute_value.h @@ -22,6 +22,7 @@ using AttributeValue = nostd::variant, nostd::span, nostd::span, + nostd::span, nostd::span>; } // namespace common OPENTELEMETRY_END_NAMESPACE