From d4f27f3884b18ca6e14854b3a454438e2f32c544 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Wed, 26 Mar 2025 14:57:12 +0100 Subject: [PATCH 1/2] Migrated CI to recent compilers --- .github/workflows/linux.yml | 68 +- .github/workflows/osx.yml | 5 +- include/xtl/xany.hpp | 477 ------ include/xtl/xvariant.hpp | 206 --- include/xtl/xvariant_impl.hpp | 2818 --------------------------------- test/test_xvariant.cpp | 228 --- 6 files changed, 30 insertions(+), 3772 deletions(-) delete mode 100644 include/xtl/xany.hpp delete mode 100644 include/xtl/xvariant.hpp delete mode 100644 include/xtl/xvariant_impl.hpp delete mode 100644 test/test_xvariant.cpp diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e08cba9..304db28 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -12,53 +12,41 @@ defaults: shell: bash -l {0} jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 name: '${{ matrix.sys.compiler }} ${{ matrix.sys.version }}' strategy: matrix: sys: - - { compiler: 'gcc', version: '7' } - - { compiler: 'gcc', version: '8' } - - { compiler: 'gcc', version: '9' } - - { compiler: 'gcc', version: '10' } - { compiler: 'gcc', version: '11' } - - { compiler: 'clang', version: '8' } - - { compiler: 'clang', version: '10' } - - { compiler: 'clang', version: '12' } - - { compiler: 'clang', version: '13' } - - { compiler: 'clang', version: '14' } - - { compiler: 'clang', version: '15' } + - { compiler: 'gcc', version: '12' } + - { compiler: 'gcc', version: '13' } + - { compiler: 'gcc', version: '14' } + - { compiler: 'clang', version: '17' } + - { compiler: 'clang', version: '18' } + - { compiler: 'clang', version: '19' } + - { compiler: 'clang', version: '20' } steps: - - name: Setup compiler - if: ${{ matrix.sys.compiler == 'gcc' }} - run: | - GCC_VERSION=${{ matrix.sys.version }} - sudo apt-get update - sudo apt-get --no-install-suggests --no-install-recommends install g++-$GCC_VERSION - CC=gcc-$GCC_VERSION - echo "CC=$CC" >> $GITHUB_ENV - CXX=g++-$GCC_VERSION - echo "CXX=$CXX" >> $GITHUB_ENV + - name: Install GCC + if: matrix.sys.compiler == 'gcc' + uses: egor-tensin/setup-gcc@v1 + with: + version: ${{matrix.sys.version}} + platform: x64 - - name: Setup compiler - if: ${{ matrix.sys.compiler == 'clang' }} + - name: Install LLVM and Clang + if: matrix.sys.compiler == 'clang' run: | - LLVM_VERSION=${{ matrix.sys.version }} - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - || exit 1 - if [[ $LLVM_VERSION -ge 13 ]]; then - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-$LLVM_VERSION main" || exit 1 - else - sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main" || exit 1 - fi || exit 1 - sudo apt-get update || exit 1 - sudo apt-get --no-install-suggests --no-install-recommends install clang-$LLVM_VERSION || exit 1 - sudo apt-get --no-install-suggests --no-install-recommends install g++-9 g++-9-multilib || exit 1 - sudo ln -s /usr/include/asm-generic /usr/include/asm - CC=clang-$LLVM_VERSION - echo "CC=$CC" >> $GITHUB_ENV - CXX=clang++-$LLVM_VERSION - echo "CXX=$CXX" >> $GITHUB_ENV + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{matrix.sys.version}} + sudo apt-get install -y clang-tools-${{matrix.sys.version}} + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{matrix.sys.version}} 200 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${{matrix.sys.version}} 200 + sudo update-alternatives --install /usr/bin/clang-scan-deps clang-scan-deps /usr/bin/clang-scan-deps-${{matrix.sys.version}} 200 + sudo update-alternatives --set clang /usr/bin/clang-${{matrix.sys.version}} + sudo update-alternatives --set clang++ /usr/bin/clang++-${{matrix.sys.version}} + sudo update-alternatives --set clang-scan-deps /usr/bin/clang-scan-deps-${{matrix.sys.version}} - name: Checkout code uses: actions/checkout@v3 @@ -70,10 +58,8 @@ jobs: cache-environment: true - name: Configure - env: - CC: ${{ env.CC }} - CXX: ${{ env.CXX }} run: | + if [[ "${{matrix.sys.compiler}}" = "gcc" ]]; then export CC=gcc-${{matrix.sys.version}}; export CXX=g++-${{matrix.sys.version}}; else export CC=clang; export CXX=clang++; fi mkdir -p build cd build cmake .. -DBUILD_TESTS=ON \ diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml index 0a794f3..c8217ba 100644 --- a/.github/workflows/osx.yml +++ b/.github/workflows/osx.yml @@ -12,8 +12,9 @@ jobs: strategy: matrix: os: - - 11 - - 12 + - 13 + - 14 + - 15 runs-on: macos-${{ matrix.os }} name: 'macos-${{ matrix.os }}' diff --git a/include/xtl/xany.hpp b/include/xtl/xany.hpp deleted file mode 100644 index f64834a..0000000 --- a/include/xtl/xany.hpp +++ /dev/null @@ -1,477 +0,0 @@ -/*************************************************************************** -* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTL_ANY_HPP -#define XTL_ANY_HPP - -#include -#include -#include -#include - -#include "xtl/xmeta_utils.hpp" - -namespace xtl -{ - /************************************** - * Implementation of C++17's std::any * - **************************************/ - - // Copyright (c) 2016 Denilson das Mercês Amorim - // - // Distributed under the Boost Software License, Version 1.0. (See accompanying - // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - - class bad_any_cast : public std::bad_cast - { - public: - - const char* what() const noexcept override - { - return "bad any cast"; - } - }; - - namespace detail { - inline static void check_any_cast(const void* p) { - if (p == nullptr) { -#if defined(XTL_NO_EXCEPTIONS) - std::fprintf(stderr, "bad_any_cast\n"); - std::terminate(); -#else - throw bad_any_cast(); -#endif - } - } - } // namespace detail - - class any final - { - public: - - /// Constructs an object of type any with an empty state. - any() - : vtable(nullptr) - { - } - - /// Constructs an object of type any with an equivalent state as other. - any(const any& rhs) - : vtable(rhs.vtable) - { - if (!rhs.empty()) - { - rhs.vtable->copy(rhs.storage, this->storage); - } - } - - /// Constructs an object of type any with a state equivalent to the original state of other. - /// rhs is left in a valid but otherwise unspecified state. - any(any&& rhs) noexcept - : vtable(rhs.vtable) - { - if (!rhs.empty()) - { - rhs.vtable->move(rhs.storage, this->storage); - rhs.vtable = nullptr; - } - } - - /// Same effect as this->clear(). - ~any() - { - this->clear(); - } - - /// Constructs an object of type any that contains an object of type T direct-initialized with std::forward(value). - /// - /// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed. - /// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed. - template ::type, any>::value>::type> - any(ValueType&& value) - { - static_assert(std::is_copy_constructible::type>::value, - "T shall satisfy the CopyConstructible requirements."); - this->construct(std::forward(value)); - } - - /// Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown. - any& operator=(const any& rhs) - { - any(rhs).swap(*this); - return *this; - } - - /// Has the same effect as any(std::move(rhs)).swap(*this). - /// - /// The state of *this is equivalent to the original state of rhs and rhs is left in a valid - /// but otherwise unspecified state. - any& operator=(any&& rhs) noexcept - { - any(std::move(rhs)).swap(*this); - return *this; - } - - /// Has the same effect as any(std::forward(value)).swap(*this). No effect if a exception is thrown. - /// - /// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed. - /// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed. - template ::type, any>::value>::type> - any& operator=(ValueType&& value) - { - static_assert(std::is_copy_constructible::type>::value, - "T shall satisfy the CopyConstructible requirements."); - any(std::forward(value)).swap(*this); - return *this; - } - - /// If not empty, destroys the contained object. - void clear() noexcept - { - if (!empty()) - { - this->vtable->destroy(storage); - this->vtable = nullptr; - } - } - - /// C++17 equivalent of clear - void reset() noexcept - { - clear(); - } - - /// Returns true if *this has no contained object, otherwise false. - bool empty() const noexcept - { - return this->vtable == nullptr; - } - - /// C++17 equivalent of !empty() - bool has_value() const noexcept - { - return !empty(); - } - - /// If *this has a contained object of type T, typeid(T); otherwise typeid(void). - const std::type_info& type() const noexcept - { - return empty() ? typeid(void) : this->vtable->type(); - } - - /// Exchange the states of *this and rhs. - void swap(any& rhs) noexcept - { - if (this->vtable != rhs.vtable) - { - any tmp(std::move(rhs)); - - // move from *this to rhs. - rhs.vtable = this->vtable; - if (this->vtable != nullptr) - { - this->vtable->move(this->storage, rhs.storage); - //this->vtable = nullptr; -- uneeded, see below - } - - // move from tmp (previously rhs) to *this. - this->vtable = tmp.vtable; - if (tmp.vtable != nullptr) - { - tmp.vtable->move(tmp.storage, this->storage); - tmp.vtable = nullptr; - } - } - else // same types - { - if (this->vtable != nullptr) - this->vtable->swap(this->storage, rhs.storage); - } - } - - private: // Storage and Virtual Method Table - - union storage_union { - using stack_storage_t = typename std::aligned_storage<2 * sizeof(void*), std::alignment_of::value>::type; - - void* dynamic; - stack_storage_t stack; // 2 words for e.g. shared_ptr - }; - - /// Base VTable specification. - struct vtable_type - { - // Note: The caller is responssible for doing .vtable = nullptr after destructful operations - // such as destroy() and/or move(). - - /// The type of the object this vtable is for. - const std::type_info& (*type)() noexcept; - - /// Destroys the object in the union. - /// The state of the union after this call is unspecified, caller must ensure not to use src anymore. - void (*destroy)(storage_union&) noexcept; - - /// Copies the **inner** content of the src union into the yet unitialized dest union. - /// As such, both inner objects will have the same state, but on separate memory locations. - void (*copy)(const storage_union& src, storage_union& dest); - - /// Moves the storage from src to the yet unitialized dest union. - /// The state of src after this call is unspecified, caller must ensure not to use src anymore. - void (*move)(storage_union& src, storage_union& dest) noexcept; - - /// Exchanges the storage between lhs and rhs. - void (*swap)(storage_union& lhs, storage_union& rhs) noexcept; - }; - - /// VTable for dynamically allocated storage. - template - struct vtable_dynamic - { - static const std::type_info& type() noexcept - { - return typeid(T); - } - - static void destroy(storage_union& storage) noexcept - { - //assert(reinterpret_cast(storage.dynamic)); - delete reinterpret_cast(storage.dynamic); - } - - static void copy(const storage_union& src, storage_union& dest) - { - dest.dynamic = new T(*reinterpret_cast(src.dynamic)); - } - - static void move(storage_union& src, storage_union& dest) noexcept - { - dest.dynamic = src.dynamic; - src.dynamic = nullptr; - } - - static void swap(storage_union& lhs, storage_union& rhs) noexcept - { - // just exchage the storage pointers. - std::swap(lhs.dynamic, rhs.dynamic); - } - }; - - /// VTable for stack allocated storage. - template - struct vtable_stack - { - static const std::type_info& type() noexcept - { - return typeid(T); - } - - static void destroy(storage_union& storage) noexcept - { - reinterpret_cast(&storage.stack)->~T(); - } - - static void copy(const storage_union& src, storage_union& dest) - { - new (&dest.stack) T(reinterpret_cast(src.stack)); - } - - static void move(storage_union& src, storage_union& dest) noexcept - { - // one of the conditions for using vtable_stack is a nothrow move constructor, - // so this move constructor will never throw a exception. - new (&dest.stack) T(std::move(reinterpret_cast(src.stack))); - destroy(src); - } - - static void swap(storage_union& lhs, storage_union& rhs) noexcept - { - storage_union tmp_storage; - move(rhs, tmp_storage); - move(lhs, rhs); - move(tmp_storage, lhs); - } - }; - - /// Whether the type T must be dynamically allocated or can be stored on the stack. - template - struct requires_allocation : std::integral_constant::value // N4562 �6.3/3 [any.class] - && sizeof(T) <= sizeof(storage_union::stack) && std::alignment_of::value <= std::alignment_of::value)> - { - }; - - /// Returns the pointer to the vtable of the type T. - template - static vtable_type* vtable_for_type() - { - using VTableType = typename std::conditional::value, vtable_dynamic, vtable_stack>::type; - static vtable_type table = { - VTableType::type, VTableType::destroy, - VTableType::copy, VTableType::move, - VTableType::swap, - }; - return &table; - } - - protected: - template - friend const T* any_cast(const any* operand) noexcept; - template - friend T* any_cast(any* operand) noexcept; - - /// Same effect as is_same(this->type(), t); - bool is_typed(const std::type_info& t) const - { - return is_same(this->type(), t); - } - - /// Checks if two type infos are the same. - /// - /// If ANY_IMPL_FAST_TYPE_INFO_COMPARE is defined, checks only the address of the - /// type infos, otherwise does an actual comparision. Checking addresses is - /// only a valid approach when there's no interaction with outside sources - /// (other shared libraries and such). - static bool is_same(const std::type_info& a, const std::type_info& b) - { -#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE - return &a == &b; -#else - return a == b; -#endif - } - - /// Casts (with no type_info checks) the storage pointer as const T*. - template - const T* cast() const noexcept - { - return requires_allocation::type>::value ? reinterpret_cast(storage.dynamic) : reinterpret_cast(&storage.stack); - } - - /// Casts (with no type_info checks) the storage pointer as T*. - template - T* cast() noexcept - { - return requires_allocation::type>::value ? reinterpret_cast(storage.dynamic) : reinterpret_cast(&storage.stack); - } - - private: - - storage_union storage; // on offset(0) so no padding for align - vtable_type* vtable; - - /// Chooses between stack and dynamic allocation for the type decay_t, - /// assigns the correct vtable, and constructs the object on our storage. - template - void construct(ValueType&& value) - { - using T = typename std::decay::type; - - this->vtable = vtable_for_type(); - - return xtl::mpl::static_if::value>([&](auto self) - { - self(*this).storage.dynamic = new T(std::forward(value)); - }, /*else*/ [&](auto self) - { - new (&self(*this).storage.stack) T(std::forward(value)); - }); - } - }; - - - namespace detail - { - template - inline ValueType any_cast_move_if_true(typename std::remove_reference::type* p, std::true_type) - { - return std::move(*p); - } - - template - inline ValueType any_cast_move_if_true(typename std::remove_reference::type* p, std::false_type) - { - return *p; - } - } - - /// Performs *any_cast>>(&operand), or throws bad_any_cast on failure. - template - inline ValueType any_cast(const any& operand) - { - auto p = any_cast::type>::type>(&operand); - detail::check_any_cast(p); - return *p; - } - - /// Performs *any_cast>(&operand), or throws bad_any_cast on failure. - template - inline ValueType any_cast(any& operand) - { - auto p = any_cast::type>(&operand); - detail::check_any_cast(p); - return *p; - } - - /// - /// If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies: - /// Performs *any_cast>(&operand), or throws bad_any_cast on failure. - /// - /// If ANY_IMPL_ANYCAST_MOVEABLE is defined, does as LWG Defect 2509 specifies: - /// If ValueType is MoveConstructible and isn't a lvalue reference, performs - /// std::move(*any_cast>(&operand)), otherwise - /// *any_cast>(&operand). Throws bad_any_cast on failure. - /// - template - inline ValueType any_cast(any&& operand) - { -#ifdef ANY_IMPL_ANY_CAST_MOVEABLE - // https://cplusplus.github.io/LWG/lwg-active.html#2509 - using can_move = std::integral_constant::value && !std::is_lvalue_reference::value>; -#else - using can_move = std::false_type; -#endif - - auto p = any_cast::type>(&operand); - detail::check_any_cast(p); - return detail::any_cast_move_if_true(p, can_move()); - } - - /// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object - /// contained by operand, otherwise nullptr. - template - inline const T* any_cast(const any* operand) noexcept - { - if (operand == nullptr || !operand->is_typed(typeid(T))) - return nullptr; - else - return operand->cast(); - } - - /// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object - /// contained by operand, otherwise nullptr. - template - inline T* any_cast(any* operand) noexcept - { - if (operand == nullptr || !operand->is_typed(typeid(T))) - return nullptr; - else - return operand->cast(); - } -} - -namespace std -{ - inline void swap(xtl::any& lhs, xtl::any& rhs) noexcept - { - lhs.swap(rhs); - } -} - -#endif diff --git a/include/xtl/xvariant.hpp b/include/xtl/xvariant.hpp deleted file mode 100644 index c3ff612..0000000 --- a/include/xtl/xvariant.hpp +++ /dev/null @@ -1,206 +0,0 @@ -/*************************************************************************** -* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XTL_XVARIANT_HPP -#define XTL_XVARIANT_HPP - -#include "xvariant_impl.hpp" -#include "xclosure.hpp" -#include "xmeta_utils.hpp" - -namespace xtl -{ - using mpark::variant; - using mpark::monostate; - using mpark::bad_variant_access; - using mpark::variant_size; -#ifdef MPARK_VARIABLE_TEMPLATES - using mpark::variant_size_v; -#endif - using mpark::variant_alternative; - using mpark::variant_alternative_t; - using mpark::variant_npos; - - using mpark::visit; - using mpark::holds_alternative; - using mpark::get; - using mpark::get_if; - - namespace detail - { - template - struct xgetter - { - template - static constexpr T& get(xtl::variant& v) - { - return xtl::get(v); - } - - template - static constexpr T&& get(xtl::variant&& v) - { - return xtl::get(std::move(v)); - } - - template - static constexpr const T& get(const xtl::variant& v) - { - return xtl::get(v); - } - - template - static constexpr const T&& get(const xtl::variant&& v) - { - return xtl::get(std::move(v)); - } - }; - - template - struct xgetter - { - template - static constexpr T& get(xtl::variant& v) - { - return xtl::get>(v).get(); - } - - template - static constexpr T& get(xtl::variant&& v) - { - return xtl::get>(std::move(v)).get(); - } - - template - static constexpr const T& get(const xtl::variant& v) - { - return xtl::get>(v).get(); - } - - template - static constexpr const T& get(const xtl::variant&& v) - { - return xtl::get>(std::move(v)).get(); - } - }; - - template - struct xgetter - { - template - static constexpr const T& get(const xtl::variant& v) - { - using cl_type = xtl::xclosure_wrapper; - return get_impl(v, xtl::mpl::contains, cl_type>()); - } - - template - static constexpr const T& get(const xtl::variant&& v) - { - using cl_type = xtl::xclosure_wrapper; - return get_impl(std::move(v), xtl::mpl::contains, cl_type>()); - } - - template - static constexpr const T& get(xtl::variant& v) - { - return get(static_cast&>(v)); - } - - template - static constexpr const T& get(xtl::variant&& v) - { - return get(static_cast&&>(v)); - } - - private: - - template - static constexpr const T& get_impl(const xtl::variant& v, xtl::mpl::bool_) - { - return xtl::get>(v).get(); - } - - template - static constexpr const T& get_impl(const xtl::variant& v, xtl::mpl::bool_) - { - return static_cast&>(xtl::get>(v)).get(); - } - - template - static constexpr const T& get_impl(const xtl::variant&& v, xtl::mpl::bool_) - { - return xtl::get>(std::move(v)).get(); - } - - template - static constexpr const T& get_impl(const xtl::variant&& v, xtl::mpl::bool_) - { - return static_cast&&>(xtl::get>(std::move(v))).get(); - } - }; - } - - template - constexpr decltype(auto) xget(xtl::variant& v) - { - return detail::xgetter::get(v); - } - - template - constexpr decltype(auto) xget(xtl::variant&& v) - { - return detail::xgetter::get(std::move(v)); - } - - template - constexpr decltype(auto) xget(const xtl::variant& v) - { - return detail::xgetter::get(v); - } - - template - constexpr decltype(auto) xget(const xtl::variant&& v) - { - return detail::xgetter::get(std::move(v)); - } - - /************************ - * overload for lambdas * - ************************/ - - // This hierarchy is required since ellipsis in using declarations are not supported until C++17 - template - struct overloaded; - - template - struct overloaded : T - { - overloaded(T arg) : T(arg) {} - using T::operator(); - }; - - template - struct overloaded : T1, overloaded - { - template - overloaded(T1 t1, T2 t2, Us... args) : T1(t1), overloaded(t2, args...) {} - - using T1::operator(); - using overloaded::operator(); - }; - - template - inline overloaded make_overload(Ts... arg) - { - return overloaded{arg...}; - } -} - -#endif diff --git a/include/xtl/xvariant_impl.hpp b/include/xtl/xvariant_impl.hpp deleted file mode 100644 index 59ac749..0000000 --- a/include/xtl/xvariant_impl.hpp +++ /dev/null @@ -1,2818 +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) - -// We cannot keep the header guard from mpark variant because -// this can conflict with other libraries that depend on or embed -// mpark variant. -#ifndef XTL_MPARK_VARIANT_HPP -#define XTL_MPARK_VARIANT_HPP - -/* - 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 - -// 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 XTL_MPARK_CONFIG_HPP -#define XTL_MPARK_CONFIG_HPP - -// MSVC 2015 Update 3. -#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) -#error "MPark.Variant requires C++11 support." -#endif - -#ifndef __has_attribute -#define __has_attribute(x) 0 -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#ifndef __has_include -#define __has_include(x) 0 -#endif - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if __has_attribute(always_inline) || defined(__GNUC__) -#define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline -#elif defined(_MSC_VER) -#define MPARK_ALWAYS_INLINE __forceinline -#else -#define MPARK_ALWAYS_INLINE inline -#endif - -#if __has_builtin(__builtin_addressof) || \ - (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) -#define MPARK_BUILTIN_ADDRESSOF -#endif - -#if __has_builtin(__builtin_unreachable) || defined(__GNUC__) -#define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable() -#elif defined(_MSC_VER) -#define MPARK_BUILTIN_UNREACHABLE __assume(false) -#else -#define MPARK_BUILTIN_UNREACHABLE -#endif - -#if __has_builtin(__type_pack_element) -#define MPARK_TYPE_PACK_ELEMENT -#endif - -#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \ - !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9) -#define MPARK_CPP11_CONSTEXPR -#endif - -#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 -#define MPARK_CPP14_CONSTEXPR -#endif - -#if !defined(MPARK_NO_EXCEPTIONS) && \ - (__has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ - defined(__EXCEPTIONS) || (defined(_MSC_VER) && defined(_CPPUNWIND))) -// Exceptions are enabled. -#define MPARK_EXCEPTIONS -#endif - -#if defined(__cpp_generic_lambdas) || defined(_MSC_VER) -#define MPARK_GENERIC_LAMBDAS -#endif - -#if defined(__cpp_lib_integer_sequence) -#define MPARK_INTEGER_SEQUENCE -#endif - -#if defined(__cpp_return_type_deduction) || defined(_MSC_VER) -#define MPARK_RETURN_TYPE_DEDUCTION -#endif - -#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) -#define MPARK_TRANSPARENT_OPERATORS -#endif - -#if defined(__cpp_variable_templates) || defined(_MSC_VER) -#define MPARK_VARIABLE_TEMPLATES -#endif - -#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 -#define MPARK_TRIVIALITY_TYPE_TRAITS -#define MPARK_INCOMPLETE_TYPE_TRAITS -#endif - -#endif // XTL_MPARK_CONFIG_HPP - -// 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 XTL_MPARK_IN_PLACE_HPP -#define XTL_MPARK_IN_PLACE_HPP - -#include - - -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 // XTL_MPARK_IN_PLACE_HPP - -// 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 XTL_MPARK_LIB_HPP -#define XTL_MPARK_LIB_HPP - -#include -#include -#include -#include - - -#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 - 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; - - namespace detail { - - template - struct is_nothrow_invocable { - static constexpr bool value = - noexcept(lib::invoke(std::declval(), std::declval()...)); - }; - - template - struct is_nothrow_invocable : std::false_type {}; - - template - struct is_nothrow_invocable_r { - private: - inline static R impl() { - return lib::invoke(std::declval(), std::declval()...); - } - - public: - static constexpr bool value = noexcept(impl()); - }; - - template - struct is_nothrow_invocable_r : std::false_type {}; - - } // namespace detail - - template - using is_nothrow_invocable = detail:: - is_nothrow_invocable::value, F, Args...>; - - template - using is_nothrow_invocable_r = - detail::is_nothrow_invocable_r::value, - R, - F, - Args...>; - - // -#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 - - -namespace mpark { - -#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; - -#ifdef MPARK_VARIABLE_TEMPLATES - template - constexpr std::size_t variant_size_v = variant_size::value; -#endif - - 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); - -#ifdef MPARK_CPP14_CONSTEXPR - template - inline constexpr std::size_t find_index() { - constexpr lib::array matches = { - {std::is_same::value...} - }; - std::size_t result = not_found; - for (std::size_t i = 0; i < sizeof...(Ts); ++i) { - if (matches[i]) { - if (result != not_found) { - return ambiguous; - } - result = i; - } - } - return result; - } -#else - 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...); - } -#endif - - 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; - } - -#ifdef MPARK_CPP14_CONSTEXPR - template - inline constexpr Trait common_trait(Traits... traits_) { - Trait result = Trait::TriviallyAvailable; - lib::array traits = {{traits_...}}; - for (std::size_t i = 0; i < sizeof...(Traits); ++i) { - Trait t = traits[i]; - if (static_cast(t) > static_cast(result)) { - result = t; - } - } - return result; - } -#else - 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...); - } -#endif - - 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 { -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { - return lib::forward(v).head_; - } - - template - inline static constexpr auto &&get_alt(V &&v, in_place_index_t) { - return get_alt(lib::forward(v).tail_, in_place_index_t{}); - } -#else - 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))) -#endif - }; - - 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))...); - } - -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto impl(lib::index_sequence) { - return &dispatch; - } - - template - inline static constexpr auto impl(Is, - lib::index_sequence, - Ls... ls) { - return make_farray(impl(lib::push_back_t{}, ls...)...); - } -#else - 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...>{}()...)) - }; -#endif - }; - -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto make_fmatrix() { - return make_fmatrix_impl::impl( - lib::index_sequence<>{}, - lib::make_index_sequence::size()>{}...); - } -#else - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN( - typename make_fmatrix_impl::template impl< - lib::index_sequence<>, - lib::make_index_sequence::size()>...>{}()) -#endif - - 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 - - using index_t = unsigned int; - - 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: -#ifndef MPARK_GENERIC_LAMBDAS - 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; - }; -#endif - - 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(), -#ifdef MPARK_GENERIC_LAMBDAS - [this](auto &this_alt, auto &&that_alt) { - this->assign_alt( - this_alt, lib::forward(that_alt).value); - } -#else - assigner{this} -#endif - , - *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=; - - 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(), -#ifdef MPARK_GENERIC_LAMBDAS - [](auto &this_alt, auto &that_alt) { - using std::swap; - swap(this_alt.value, - that_alt.value); - } -#else - swapper{} -#endif - , - *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: -#ifndef MPARK_GENERIC_LAMBDAS - struct swapper { - template - inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { - using std::swap; - swap(this_alt.value, that_alt.value); - } - }; -#endif - - 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 overload_leaf { - using F = lib::size_constant (*)(T); - operator F() 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, T &&>; - - 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; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.index() != rhs.index()) return false; - if (lhs.valueless_by_exception()) return true; - return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); -#else - return lhs.index() == rhs.index() && - (lhs.valueless_by_exception() || - variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); -#endif - } - - template - inline constexpr bool operator!=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using not_equal_to = detail::convert_to_bool; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.index() != rhs.index()) return true; - if (lhs.valueless_by_exception()) return false; - return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); -#else - return lhs.index() != rhs.index() || - (!lhs.valueless_by_exception() && - variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); -#endif - } - - template - inline constexpr bool operator<(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using less = detail::convert_to_bool; -#ifdef MPARK_CPP14_CONSTEXPR - if (rhs.valueless_by_exception()) return false; - if (lhs.valueless_by_exception()) return true; - if (lhs.index() < rhs.index()) return true; - if (lhs.index() > rhs.index()) return false; - return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); -#else - 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))); -#endif - } - - template - inline constexpr bool operator>(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using greater = detail::convert_to_bool; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.valueless_by_exception()) return false; - if (rhs.valueless_by_exception()) return true; - if (lhs.index() > rhs.index()) return true; - if (lhs.index() < rhs.index()) return false; - return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); -#else - 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))); -#endif - } - - template - inline constexpr bool operator<=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using less_equal = detail::convert_to_bool; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.valueless_by_exception()) return true; - if (rhs.valueless_by_exception()) return false; - if (lhs.index() < rhs.index()) return true; - if (lhs.index() > rhs.index()) return false; - return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); -#else - 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)))); -#endif - } - - template - inline constexpr bool operator>=(const variant &lhs, - const variant &rhs) { - using detail::visitation::variant; - using greater_equal = detail::convert_to_bool; -#ifdef MPARK_CPP14_CONSTEXPR - if (rhs.valueless_by_exception()) return true; - if (lhs.valueless_by_exception()) return false; - if (lhs.index() > rhs.index()) return true; - if (lhs.index() < rhs.index()) return false; - return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); -#else - 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)))); -#endif - } - - 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; - } - -#ifdef MPARK_CPP14_CONSTEXPR - namespace detail { - - inline constexpr bool any(std::initializer_list bs) { - for (bool b : bs) { - if (b) { - return true; - } - } - return false; - } - - } // namespace detail - - template - inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { - return (!detail::any({vs.valueless_by_exception()...}) - ? (void)0 - : throw_bad_variant_access()), - detail::visitation::variant::visit_value( - lib::forward(visitor), lib::forward(vs)...); - } -#else - 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)...)) -#endif - - 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 mpark - -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( -#ifdef MPARK_GENERIC_LAMBDAS - [](const auto &alt) { - using alt_type = mpark::lib::decay_t; - using value_type = mpark::lib::remove_const_t< - typename alt_type::value_type>; - return hash{}(alt.value); - } -#else - hasher{} -#endif - , - v); - return hash_combine(result, hash{}(v.index())); - } - - private: -#ifndef MPARK_GENERIC_LAMBDAS - 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); - } - }; -#endif - - 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 - -#endif // MPARK_VARIANT_HPP diff --git a/test/test_xvariant.cpp b/test/test_xvariant.cpp deleted file mode 100644 index 2c485b4..0000000 --- a/test/test_xvariant.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/*************************************************************************** -* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#include "xtl/xvariant.hpp" - -#include -#include - -#include "test_common_macros.hpp" -#include "xtl/xtl_config.hpp" - -#ifdef HAVE_NLOHMANN_JSON -#include "xtl/xjson.hpp" -#endif - -using namespace std::literals; - -namespace xtl -{ - TEST(xvariant, basic) - { - xtl::variant v, w; - v = 12; - int i = xtl::get(v); - EXPECT_EQ(12, i); - - w = xtl::get(v); - EXPECT_EQ(12, xtl::get(w)); - w = xtl::get<0>(v); - EXPECT_EQ(12, xtl::get(w)); - w = v; - EXPECT_EQ(12, xtl::get(w)); - } - - TEST(xvariant, bad_variant_access) - { - xtl::variant v; - v = 12; -#if defined(XTL_NO_EXCEPTIONS) - EXPECT_DEATH_IF_SUPPORTED(xtl::get(v), ""); -#else - EXPECT_THROW(xtl::get(v), xtl::bad_variant_access); -#endif - } - - TEST(xvariant, converting_constructor) - { - xtl::variant x("abc"); - x = "def"; - EXPECT_EQ(std::string("def"), xtl::get(x)); - } - - TEST(xvariant, holds_alternative) - { - xtl::variant y("abc"); - EXPECT_TRUE(xtl::holds_alternative(y)); - y = "xyz"s; - EXPECT_TRUE(xtl::holds_alternative(y)); - } - - TEST(xvariant, visit) - { - using var_t = xtl::variant; - std::vector vec = { 10, 15l, 1.5, "hello" }; - std::vector vec_res(4); - for (std::size_t i = 0; i < vec.size(); ++i) - { - var_t v = vec[i]; - var_t w = xtl::visit([](auto&& arg) -> var_t {return arg + arg; }, v); - vec_res[i] = w; - } - EXPECT_EQ(20, xtl::get<0>(vec_res[0])); - EXPECT_EQ(30l, xtl::get<1>(vec_res[1])); - EXPECT_EQ(3., xtl::get<2>(vec_res[2])); - EXPECT_EQ("hellohello", xtl::get<3>(vec_res[3])); - } - - using variant_ref = xtl::variant, xclosure_wrapper>; - - variant_ref build_test_variant(int& ref) - { - variant_ref res(closure(ref)); - return res; - } - - const variant_ref build_test_cvariant(int& ref) - { - variant_ref res(closure(ref)); - return res; - } - - TEST(xvariant, closure_wrapper) - { - { - int i = 2; - variant_ref v = closure(i); - int& ir = xtl::xget(v); - EXPECT_EQ(&ir, &i); - ir = 4; - EXPECT_EQ(i, 4); - int ir2 = xtl::xget(v); - EXPECT_EQ(ir2, i); - - const int& cir = xtl::xget(v); - EXPECT_EQ(&cir, &i); - } - - { - int i = 2; - const variant_ref v = closure(i); - const int& ir = xtl::xget(v); - EXPECT_EQ(&ir, &i); - int ir2 = xtl::xget(v); - EXPECT_EQ(ir2, i); - - const int& cir = xtl::xget(v); - EXPECT_EQ(&cir, &i); - } - - { - int i = 2; - int& ir = xtl::xget(build_test_variant(i)); - EXPECT_EQ(&ir, &i); - ir = 4; - EXPECT_EQ(i, 4); - - const int& cir = xtl::xget(build_test_variant(i)); - EXPECT_EQ(&cir,&i); - } - - { - int i = 2; - const int& ir = xtl::xget(build_test_cvariant(i)); - EXPECT_EQ(&ir, &i); - i = 4; - EXPECT_EQ(ir, i); - - const int& cir = xtl::xget(build_test_cvariant(i)); - EXPECT_EQ(&cir,&i); - } - } - - using variant_cref = xtl::variant, xclosure_wrapper>; - - variant_cref build_test_variant(const int& ref) - { - variant_cref res(closure(ref)); - return res; - } - - const variant_cref build_test_cvariant(const int& ref) - { - variant_cref res(closure(ref)); - return res; - } - - - TEST(xvariant, const_closure_wrapper) - { - { - const int i = 2; - variant_cref v = closure(i); - const int& cir = xtl::xget(v); - EXPECT_EQ(&cir, &i); - } - - { - const int i = 2; - const variant_cref v = closure(i); - const int& cir = xtl::xget(v); - EXPECT_EQ(&cir, &i); - } - - { - const int i = 2; - const int& cir = xtl::xget(build_test_variant(i)); - EXPECT_EQ(&cir, &i); - } - - { - const int i = 2; - const int& cir = xtl::xget(build_test_cvariant(i)); - EXPECT_EQ(&cir, &i); - } - } - - TEST(xvariant, overloaded_lambdas) - { - using var_t = xtl::variant; - std::vector vec = { 1, 2.5, "hello" }; - - bool res = true; - - for (auto& v : vec) - { - res &= xtl::visit(xtl::make_overload([](int arg) { return arg == 1; }, - [](double arg) { return arg == 2.5; }, - [](const std::string& arg) { return arg == "hello"; }), - v); - } - - EXPECT_TRUE(res); - } - -#ifdef HAVE_NLOHMANN_JSON - TEST(xvariant, json) - { - typedef xtl::variant stringNumType; - - nlohmann::json j1; - stringNumType m1 = "Hello"; - j1["salutation"] = m1; - EXPECT_EQ(j1.at("salutation"), "Hello"); - - nlohmann::json j2; - stringNumType m2 = 3.0; - j2["num"] = m2; - EXPECT_EQ(j2.at("num"), 3.0); - } -#endif - -} From fe2a7206d3b36c48a5d4f574726c1585270474db Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Wed, 26 Mar 2025 14:57:44 +0100 Subject: [PATCH 2/2] Migrated to C++17 and replaced backported features with standard ones --- CMakeLists.txt | 33 +++---------- docs/source/basic_types.rst | 37 --------------- include/xtl/xcomplex.hpp | 12 ++--- include/xtl/xjson.hpp | 14 ------ include/xtl/xmasked_value.hpp | 16 +++---- include/xtl/xmeta_utils.hpp | 35 -------------- include/xtl/xoptional.hpp | 70 ++++++++++++++-------------- include/xtl/xoptional_meta.hpp | 8 ++-- include/xtl/xsequence.hpp | 28 +----------- include/xtl/xtype_traits.hpp | 84 ++-------------------------------- test/CMakeLists.txt | 3 +- test/test_xmeta_utils.cpp | 64 ++------------------------ test/test_xoptional.cpp | 6 +-- test/test_xtype_traits.cpp | 32 ++++++------- 14 files changed, 90 insertions(+), 352 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2429881..796dc46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ # The full license is in the file LICENSE, distributed with this software. # ############################################################################ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.29) project(xtl) set(XTL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -37,7 +37,6 @@ endif() # ===== set(XTL_HEADERS - ${XTL_INCLUDE_DIR}/xtl/xany.hpp ${XTL_INCLUDE_DIR}/xtl/xbasic_fixed_string.hpp ${XTL_INCLUDE_DIR}/xtl/xbase64.hpp ${XTL_INCLUDE_DIR}/xtl/xclosure.hpp @@ -67,8 +66,6 @@ set(XTL_HEADERS ${XTL_INCLUDE_DIR}/xtl/xsystem.hpp ${XTL_INCLUDE_DIR}/xtl/xtl_config.hpp ${XTL_INCLUDE_DIR}/xtl/xtype_traits.hpp - ${XTL_INCLUDE_DIR}/xtl/xvariant.hpp - ${XTL_INCLUDE_DIR}/xtl/xvariant_impl.hpp ${XTL_INCLUDE_DIR}/xtl/xvisitor.hpp ) @@ -78,13 +75,11 @@ target_include_directories(xtl INTERFACE $ $) -if(NOT (CMAKE_VERSION VERSION_LESS 3.15)) # CMake >= 3.15 set_target_properties(xtl PROPERTIES PUBLIC_HEADER "${XTL_HEADERS}") -endif() -target_compile_features(xtl INTERFACE cxx_std_14) +target_compile_features(xtl INTERFACE cxx_std_17) option(BUILD_TESTS "xtl test suite" OFF) option(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF) @@ -101,24 +96,14 @@ endif() include(GNUInstallDirs) include(CMakePackageConfigHelpers) -if(CMAKE_VERSION VERSION_LESS 3.15) # CMake < 3.15 -install(TARGETS xtl - EXPORT ${PROJECT_NAME}-targets) -else() install(TARGETS xtl EXPORT ${PROJECT_NAME}-targets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) -endif() # Makes the project importable from the build directory export(EXPORT ${PROJECT_NAME}-targets FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") -if(CMAKE_VERSION VERSION_LESS 3.15) # CMake < 3.15 -install(FILES ${XTL_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtl) -endif() - set(XTL_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for xtlConfig.cmake") @@ -132,16 +117,10 @@ configure_package_config_file(${PROJECT_NAME}Config.cmake.in set(_XTL_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) unset(CMAKE_SIZEOF_VOID_P) # ARCH_INDEPENDENT feature was introduced in cmake 3.14 -if (${CMAKE_VERSION} VERSION_LESS "3.14.0") - write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${${PROJECT_NAME}_VERSION} - COMPATIBILITY AnyNewerVersion) -else () - write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${${PROJECT_NAME}_VERSION} - COMPATIBILITY AnyNewerVersion - ARCH_INDEPENDENT) -endif () +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${${PROJECT_NAME}_VERSION} + COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT) set(CMAKE_SIZEOF_VOID_P ${_XTL_CMAKE_SIZEOF_VOID_P}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake diff --git a/docs/source/basic_types.rst b/docs/source/basic_types.rst index 020799f..e7a799d 100644 --- a/docs/source/basic_types.rst +++ b/docs/source/basic_types.rst @@ -7,38 +7,6 @@ Basic types =========== -any ---- - -`xtl::any` is a backport of the C++17 class `std::any`. The class describes a -type-safe container for single values of any type: - -.. code:: - - #include - #include "xtl/xany.hpp" - - xtl::any a = 1; - std::cout << a.type().name() << ": " << xtl::any_cast(a) << std::endl; - // => i: 1 - - try - { - std::cout << xtl::any_cast(a) << std::endl; - } - catch(const xtl::bad_any_cast& e) - { - std::cout << e.what() << std::endl; - } - // => bad any_cast - - a.reset(); - std::cout << std::boolalpha << a.empty() << std::endl; - // => true - -The API of `xtl::any` is the same as that of `std::any`. Full documentation -can be found on `cppreference `_. - xbasic_fixed_string ------------------- @@ -108,8 +76,3 @@ xoptional TODO -xvariant --------- - -TODO - diff --git a/include/xtl/xcomplex.hpp b/include/xtl/xcomplex.hpp index b5ac2a5..53fb52a 100644 --- a/include/xtl/xcomplex.hpp +++ b/include/xtl/xcomplex.hpp @@ -87,7 +87,7 @@ namespace xtl ******************/ template - using is_gen_complex = disjunction>, is_xcomplex>>; + using is_gen_complex = std::disjunction>, is_xcomplex>>; /**************************** * enable / disable complex * @@ -165,8 +165,8 @@ namespace xtl template >, + std::conjunction< + std::negation>, std::is_constructible, std::is_convertible >::value, @@ -179,10 +179,10 @@ namespace xtl template >, + std::conjunction< + std::negation>, std::is_constructible, - negation> + std::negation> >::value, bool > = true> diff --git a/include/xtl/xjson.hpp b/include/xtl/xjson.hpp index a69c648..7587dd5 100644 --- a/include/xtl/xjson.hpp +++ b/include/xtl/xjson.hpp @@ -17,7 +17,6 @@ #include #include -#include "xtl/xvariant.hpp" #include "nlohmann/json.hpp" namespace xtl @@ -82,17 +81,4 @@ namespace xtl } } -// overloading in the mpark namespace because `xtl::variant` is just a typedef on `mpark::variant` -namespace mpark -{ - template - void to_json(nlohmann::json& j, const xtl::variant& data) { - xtl::visit - ( - [&j] (const auto & arg) { j = arg; }, - data - ); - } -} - #endif diff --git a/include/xtl/xmasked_value.hpp b/include/xtl/xmasked_value.hpp index 1009b4c..ebe2f57 100644 --- a/include/xtl/xmasked_value.hpp +++ b/include/xtl/xmasked_value.hpp @@ -219,13 +219,13 @@ namespace xtl return lhs.equal(rhs); } - template >)> + template >)> inline bool operator==(const T1& lhs, const xmasked_value& rhs) noexcept { return rhs.equal(lhs); } - template >)> + template >)> inline bool operator==(const xmasked_value& lhs, const T2& rhs) noexcept { return lhs.equal(rhs); @@ -237,13 +237,13 @@ namespace xtl return !lhs.equal(rhs); } - template >)> + template >)> inline bool operator!=(const T1& lhs, const xmasked_value& rhs) noexcept { return !rhs.equal(lhs); } - template >)> + template >)> inline bool operator!=(const xmasked_value& lhs, const T2& rhs) noexcept { return !lhs.equal(rhs); @@ -308,7 +308,7 @@ namespace xtl return e1.visible() && e2.visible() ? masked_value(e1.value() OP e2.value()) : masked(); \ } \ \ - template >)> \ + template >)> \ inline auto operator OP(const xmasked_value& e1, const T2& e2) noexcept \ -> xmasked_value, std::decay_t>> \ { \ @@ -316,7 +316,7 @@ namespace xtl return e1.visible() ? masked_value(e1.value() OP e2) : masked(); \ } \ \ - template >)> \ + template >)> \ inline auto operator OP(const T1& e1, const xmasked_value& e2) noexcept \ -> xmasked_value, std::decay_t>> \ { \ @@ -334,14 +334,14 @@ namespace xtl masked(); \ } \ \ - template >)> \ + template >)> \ inline auto operator OP(const xmasked_value& e1, const T2& e2) noexcept \ -> xmasked_value \ { \ return e1.visible() ? masked_value(e1.value() OP e2) : masked(); \ } \ \ - template >)> \ + template >)> \ inline auto operator OP(const T1& e1, const xmasked_value& e2) noexcept \ -> xmasked_value \ { \ diff --git a/include/xtl/xmeta_utils.hpp b/include/xtl/xmeta_utils.hpp index 2cd5aee..49599e0 100644 --- a/include/xtl/xmeta_utils.hpp +++ b/include/xtl/xmeta_utils.hpp @@ -19,19 +19,6 @@ namespace xtl { - // TODO move to a xutils if we have one - - // gcc 4.9 is affected by C++14 defect CGW 1558 - // see http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 - template - struct make_void - { - using type = void; - }; - - template - using void_t = typename make_void::type; - namespace mpl { /************* @@ -581,28 +568,6 @@ namespace xtl template using unique_t = typename unique::type; - /************* - * static_if * - *************/ - - template - decltype(auto) static_if(std::true_type, const TF& tf, const FF&) - { - return tf(identity()); - } - - template - decltype(auto) static_if(std::false_type, const TF&, const FF& ff) - { - return ff(identity()); - } - - template - decltype(auto) static_if(const TF& tf, const FF& ff) - { - return static_if(std::integral_constant(), tf, ff); - } - /*********** * switch_ * ***********/ diff --git a/include/xtl/xoptional.hpp b/include/xtl/xoptional.hpp index 1ed40c4..c875085 100644 --- a/include/xtl/xoptional.hpp +++ b/include/xtl/xoptional.hpp @@ -78,8 +78,8 @@ namespace xtl template , std::decay_t>>, + std::conjunction< + std::negation, std::decay_t>>, std::is_constructible, std::is_convertible >::value, @@ -92,10 +92,10 @@ namespace xtl template , std::decay_t>>, + std::conjunction< + std::negation, std::decay_t>>, std::is_constructible, - negation> + std::negation> >::value, bool > = false> @@ -106,15 +106,15 @@ namespace xtl template , xoptional>>, + std::conjunction< + std::negation, xoptional>>, std::is_constructible>>, std::is_constructible>>, - conjunction< + std::conjunction< std::is_convertible>, CT>, std::is_convertible>, CB> >, - negation> + std::negation> >::value, bool > = true> @@ -125,15 +125,15 @@ namespace xtl template , xoptional>>, + std::conjunction< + std::negation, xoptional>>, std::is_constructible>>, std::is_constructible>>, - disjunction< - negation>, CT>>, - negation>, CB>> + std::disjunction< + std::negation>, CT>>, + std::negation>, CB>> >, - negation> + std::negation> >::value, bool > = false> @@ -144,15 +144,15 @@ namespace xtl template , xoptional>>, + std::conjunction< + std::negation, xoptional>>, std::is_constructible::value, const std::decay_t&, std::decay_t&&>>, std::is_constructible::value, const std::decay_t&, std::decay_t&&>>, - conjunction< + std::conjunction< std::is_convertible::value, const std::decay_t&, std::decay_t&&>, CT>, std::is_convertible::value, const std::decay_t&, std::decay_t&&>, CB> >, - negation> + std::negation> >::value, bool > = true> @@ -163,15 +163,15 @@ namespace xtl template , xoptional>>, + std::conjunction< + std::negation, xoptional>>, std::is_constructible::value, const std::decay_t&, std::decay_t&&>>, std::is_constructible::value, const std::decay_t&, std::decay_t&&>>, - disjunction< - negation::value, const std::decay_t&, std::decay_t&&>, CT>>, - negation::value, const std::decay_t&, std::decay_t&&>, CB>> + std::disjunction< + std::negation::value, const std::decay_t&, std::decay_t&&>, CT>>, + std::negation::value, const std::decay_t&, std::decay_t&&>, CB>> >, - negation> + std::negation> >::value, bool > = false> @@ -188,8 +188,8 @@ namespace xtl // Assignment template std::enable_if_t< - conjunction< - negation, std::decay_t>>, + std::conjunction< + std::negation, std::decay_t>>, std::is_assignable, T> >::value, xoptional&> @@ -201,11 +201,11 @@ namespace xtl } template - std::enable_if_t, xoptional>>, + std::enable_if_t, xoptional>>, std::is_assignable, CTO>, - negation>, - negation> + std::negation>, + std::negation> >::value, xoptional&> inline operator=(const xoptional& rhs) @@ -216,11 +216,11 @@ namespace xtl } template - std::enable_if_t, xoptional>>, + std::enable_if_t, xoptional>>, std::is_assignable, CTO>, - negation>, - negation> + std::negation>, + std::negation> >::value, xoptional&> inline operator=(xoptional&& rhs) diff --git a/include/xtl/xoptional_meta.hpp b/include/xtl/xoptional_meta.hpp index ed79c44..1a57d22 100644 --- a/include/xtl/xoptional_meta.hpp +++ b/include/xtl/xoptional_meta.hpp @@ -35,7 +35,7 @@ namespace xtl }; template - using converts_from_xoptional = disjunction< + using converts_from_xoptional = std::disjunction< std::is_constructible&>, std::is_constructible&>, std::is_constructible&&>, @@ -47,7 +47,7 @@ namespace xtl >; template - using assigns_from_xoptional = disjunction< + using assigns_from_xoptional = std::disjunction< std::is_assignable, const xoptional&>, std::is_assignable, xoptional&>, std::is_assignable, const xoptional&&>, @@ -120,7 +120,7 @@ namespace xtl using disable_xoptional = std::enable_if_t::value, R>; template - struct at_least_one_xoptional : disjunction...> + struct at_least_one_xoptional : std::disjunction...> { }; @@ -133,7 +133,7 @@ namespace xtl using common_optional_t = typename common_optional::type; template - struct is_not_xoptional_nor_xmasked_value : negation, is_xmasked_value>> + struct is_not_xoptional_nor_xmasked_value : std::negation, is_xmasked_value>> { }; } diff --git a/include/xtl/xsequence.hpp b/include/xtl/xsequence.hpp index 4f27088..55c7b64 100644 --- a/include/xtl/xsequence.hpp +++ b/include/xtl/xsequence.hpp @@ -33,14 +33,6 @@ namespace xtl template decltype(auto) forward_sequence(A&& s); - // equivalent to std::size(c) in c++17 - template - constexpr auto sequence_size(const C& c) -> decltype(c.size()); - - // equivalent to std::size(a) in c++17 - template - constexpr std::size_t sequence_size(const T (&a)[N]); - /******************************** * make_sequence implementation * ********************************/ @@ -134,7 +126,7 @@ namespace xtl }; template - struct sequence_forwarder_impl().resize( + struct sequence_forwarder_impl().resize( std::declval()))>> { template @@ -183,24 +175,6 @@ namespace xtl return forwarder::forward(std::move(s)); } - /******************************** - * sequence_size implementation * - ********************************/ - - // equivalent to std::size(c) in c++17 - template - constexpr auto sequence_size(const C& c) -> decltype(c.size()) - { - return c.size(); - } - - // equivalent to std::size(a) in c++17 - template - constexpr std::size_t sequence_size(const T (&)[N]) - { - return N; - } - /**************************** * are_equivalent_sequences * ****************************/ diff --git a/include/xtl/xtype_traits.hpp b/include/xtl/xtype_traits.hpp index 07a04b3..8c36836 100644 --- a/include/xtl/xtype_traits.hpp +++ b/include/xtl/xtype_traits.hpp @@ -298,80 +298,21 @@ namespace xtl template using apply_cv_t = typename apply_cv::type; - /**************************************************************** - * C++17 logical operators (disjunction, conjunction, negation) * - ****************************************************************/ - - /******************** - * disjunction - or * - ********************/ - - template - struct disjunction; - - template <> - struct disjunction<> : std::false_type - { - }; - - template - struct disjunction : Arg - { - }; - - template - struct disjunction : std::conditional_t> - { - }; - - /********************* - * conjunction - and * - *********************/ - - template - struct conjunction; - - template <> - struct conjunction<> : std::true_type - { - }; - - template - struct conjunction : Arg1 - { - }; - - template - struct conjunction : std::conditional_t, Arg1> - { - }; - - /****************** - * negation - not * - ******************/ - - template - struct negation : std::integral_constant - { - }; - /************ * concepts * ************/ -#if !defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ >= 5)) - template - constexpr bool xtl_requires = conjunction::value; + constexpr bool xtl_requires = std::conjunction::value; template - constexpr bool either = disjunction::value; + constexpr bool either = std::disjunction::value; template - constexpr bool disallow = xtl::negation>::value; + constexpr bool disallow = std::negation>::value; template - constexpr bool disallow_one = xtl::negation>::value; + constexpr bool disallow_one = std::negation>::value; template using check_requires = std::enable_if_t, int>; @@ -385,21 +326,6 @@ namespace xtl template using check_disallow_one = std::enable_if_t, int>; -#else - - template - using check_requires = std::enable_if_t::value, int>; - - template - using check_either = std::enable_if_t::value, int>; - - template - using check_disallow = std::enable_if_t>::value, int>; - - template - using check_disallow_one = std::enable_if_t>::value, int>; - -#endif #define XTL_REQUIRES_IMPL(...) xtl::check_requires<__VA_ARGS__> #define XTL_REQUIRES(...) XTL_REQUIRES_IMPL(__VA_ARGS__) = 0 @@ -422,7 +348,7 @@ namespace xtl **************/ template - struct all_scalar : conjunction...> + struct all_scalar : std::conjunction...> { }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 955ff22..ee6ce9c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,7 +7,7 @@ # The full license is in the file LICENSE, distributed with this software. # ############################################################################ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.29) find_package(doctest REQUIRED) @@ -104,7 +104,6 @@ set(XTL_TESTS test_xplatform.cpp test_xproxy_wrapper.cpp test_xsystem.cpp - test_xvariant.cpp test_xvisitor.cpp ) diff --git a/test/test_xmeta_utils.cpp b/test/test_xmeta_utils.cpp index 48f2002..45af3dc 100644 --- a/test/test_xmeta_utils.cpp +++ b/test/test_xmeta_utils.cpp @@ -6,15 +6,17 @@ * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ + +#include + #include "xtl/xmeta_utils.hpp" #include "test_common_macros.hpp" -#include "xtl/xvariant.hpp" namespace xtl { using vector_t = mpl::vector; - using variant_t = variant; + using variant_t = std::variant; TEST(mpl, if_) { @@ -30,7 +32,7 @@ namespace xtl TEST(mpl, cast) { - using type = mpl::cast_t; + using type = mpl::cast_t; bool res = std::is_same::value; EXPECT_TRUE(res); } @@ -226,62 +228,6 @@ namespace xtl } } - template - int static_if_tester() - { - int input = 0; - return mpl::static_if([&](auto /*self*/) - { - return input; - }, /*else*/ [&](auto /*self*/) - { - return input + 1; - }); - } - - TEST(mpl, static_if) - { - int output_0 = static_if_tester(); - int output_1 = static_if_tester(); - EXPECT_EQ(output_0, 0); - EXPECT_EQ(output_1, 1); - } - - template - struct static_if_tester2 - { - int input = 0; - - inline int& operator()() - { - return mpl::static_if([&](auto /*self*/) -> int& - { - return input; - }, /*else*/ [&](auto /*self*/) -> int& - { - input++; - return input; - }); - } - }; - - TEST(mpl, static_if2) - { - static_if_tester2 tester; - int& output_0 = tester(); - EXPECT_EQ(output_0, 0); - - output_0++; - int& output_1 = tester(); - EXPECT_EQ(output_1, 1); - - static_if_tester2 tester2; - int& output_3 = tester2(); - EXPECT_EQ(output_3, 1); - tester2(); - EXPECT_EQ(output_3, 2); - } - TEST(mpl, unique) { using input1 = mpl::vector; diff --git a/test/test_xoptional.cpp b/test/test_xoptional.cpp index f6eee90..74039da 100644 --- a/test/test_xoptional.cpp +++ b/test/test_xoptional.cpp @@ -11,11 +11,11 @@ #include "xtl/xoptional_sequence.hpp" #include +#include #include #include #include -#include "xtl/xany.hpp" #include "test_common_macros.hpp" #ifdef HAVE_NLOHMANN_JSON @@ -274,9 +274,9 @@ namespace xtl double d = 1.; bool f = true; opt_type o(d, f); - xtl::any a(o); + std::any a(o); - opt_type res = any_cast(a); + opt_type res = std::any_cast(a); EXPECT_EQ(res.value(), o.value()); EXPECT_EQ(res.has_value(), o.has_value()); } diff --git a/test/test_xtype_traits.cpp b/test/test_xtype_traits.cpp index 8b6b500..43c5e9a 100644 --- a/test/test_xtype_traits.cpp +++ b/test/test_xtype_traits.cpp @@ -20,40 +20,40 @@ namespace xtl TEST(xtype_traits, conjunction) { bool res; - res = conjunction<>::value; + res = std::conjunction<>::value; EXPECT_EQ(res, true); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, false); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, false); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, false); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, true); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, true); - res = conjunction::value; + res = std::conjunction::value; EXPECT_EQ(res, false); } TEST(xtype_traits, disjunction) { bool res; - res = disjunction<>::value; + res = std::disjunction<>::value; EXPECT_EQ(res, false); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, false); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, true); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, true); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, true); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, true); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, true); - res = disjunction::value; + res = std::disjunction::value; EXPECT_EQ(res, false); } @@ -66,7 +66,7 @@ namespace xtl return 0; } - template , xtl::negation>)> + template , std::negation>)> int test_requires(T) { return 1;