brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · 8b9e94a Raw
299 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// <tuple>12 13// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);14 15#include <tuple>16#include <array>17#include <cassert>18#include <cstdint>19#include <string>20#include <utility>21 22#include "test_macros.h"23#include "type_id.h"24 25template <class Tuple>26struct ConstexprConstructibleFromTuple {27  template <class ...Args>28  explicit constexpr ConstexprConstructibleFromTuple(Args&&... xargs)29      : args{std::forward<Args>(xargs)...} {}30  Tuple args;31};32 33template <class TupleLike>34struct ConstructibleFromTuple;35 36template <template <class ...> class Tuple, class ...Types>37struct ConstructibleFromTuple<Tuple<Types...>> {38  template <class ...Args>39  explicit ConstructibleFromTuple(Args&&... xargs)40      : args(xargs...),41        arg_types(&makeArgumentID<Args&&...>())42  {}43  Tuple<std::decay_t<Types>...> args;44  TypeID const* arg_types;45};46 47template <class Tp, std::size_t N>48struct ConstructibleFromTuple<std::array<Tp, N>> {49template <class ...Args>50  explicit ConstructibleFromTuple(Args&&... xargs)51      : args{xargs...},52        arg_types(&makeArgumentID<Args&&...>())53  {}54  std::array<Tp, N> args;55  TypeID const* arg_types;56};57 58template <class Tuple>59constexpr bool do_constexpr_test(Tuple&& tup) {60    using RawTuple = std::decay_t<Tuple>;61    using Tp = ConstexprConstructibleFromTuple<RawTuple>;62    return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;63}64 65template <class ...ExpectTypes, class Tuple>66bool do_forwarding_test(Tuple&& tup) {67    using RawTuple = std::decay_t<Tuple>;68    using Tp = ConstructibleFromTuple<RawTuple>;69    const Tp value = std::make_from_tuple<Tp>(std::forward<Tuple>(tup));70    return value.args == tup71        && value.arg_types == &makeArgumentID<ExpectTypes...>();72}73 74void test_constexpr_construction() {75    {76        constexpr std::tuple<> tup;77        static_assert(do_constexpr_test(tup), "");78    }79    {80        constexpr std::tuple<int> tup(42);81        static_assert(do_constexpr_test(tup), "");82    }83    {84        constexpr std::tuple<int, long, void*> tup(42, 101, nullptr);85        static_assert(do_constexpr_test(tup), "");86    }87    {88        constexpr std::pair<int, const char*> p(42, "hello world");89        static_assert(do_constexpr_test(p), "");90    }91    {92        using Tuple = std::array<int, 3>;93        using ValueTp = ConstexprConstructibleFromTuple<Tuple>;94        constexpr Tuple arr = {42, 101, -1};95        constexpr ValueTp value = std::make_from_tuple<ValueTp>(arr);96        static_assert(value.args[0] == arr[0] && value.args[1] == arr[1]97            && value.args[2] == arr[2], "");98    }99}100 101void test_perfect_forwarding() {102    {103        using Tup = std::tuple<>;104        Tup tup;105        Tup const& ctup = tup;106        assert(do_forwarding_test<>(tup));107        assert(do_forwarding_test<>(ctup));108    }109    {110        using Tup = std::tuple<int>;111        Tup tup(42);112        Tup const& ctup = tup;113        assert(do_forwarding_test<int&>(tup));114        assert(do_forwarding_test<int const&>(ctup));115        assert(do_forwarding_test<int&&>(std::move(tup)));116        assert(do_forwarding_test<int const&&>(std::move(ctup)));117    }118    {119        using Tup = std::tuple<int&, const char*, unsigned&&>;120        int x = 42;121        unsigned y = 101;122        Tup tup(x, "hello world", std::move(y));123        Tup const& ctup = tup;124        assert((do_forwarding_test<int&, const char*&, unsigned&>(tup)));125        assert((do_forwarding_test<int&, const char* const&, unsigned &>(ctup)));126        assert((do_forwarding_test<int&, const char*&&, unsigned&&>(std::move(tup))));127        assert((do_forwarding_test<int&, const char* const&&, unsigned &&>(std::move(ctup))));128    }129    // test with pair<T, U>130    {131        using Tup = std::pair<int&, const char*>;132        int x = 42;133        Tup tup(x, "hello world");134        Tup const& ctup = tup;135        assert((do_forwarding_test<int&, const char*&>(tup)));136        assert((do_forwarding_test<int&, const char* const&>(ctup)));137        assert((do_forwarding_test<int&, const char*&&>(std::move(tup))));138        assert((do_forwarding_test<int&, const char* const&&>(std::move(ctup))));139    }140    // test with array<T, I>141    {142        using Tup = std::array<int, 3>;143        Tup tup = {42, 101, -1};144        Tup const& ctup = tup;145        assert((do_forwarding_test<int&, int&, int&>(tup)));146        assert((do_forwarding_test<int const&, int const&, int const&>(ctup)));147        assert((do_forwarding_test<int&&, int&&, int&&>(std::move(tup))));148        assert((do_forwarding_test<int const&&, int const&&, int const&&>(std::move(ctup))));149    }150}151 152void test_noexcept() {153    struct NothrowMoveable {154      NothrowMoveable() = default;155      NothrowMoveable(NothrowMoveable const&) {}156      NothrowMoveable(NothrowMoveable&&) noexcept {}157    };158    struct TestType {159      TestType(int, NothrowMoveable) noexcept {}160      TestType(int, int, int) noexcept(false) {}161      TestType(long, long, long) noexcept {}162    };163    {164        using Tuple = std::tuple<int, NothrowMoveable>;165        Tuple tup; ((void)tup);166        Tuple const& ctup = tup; ((void)ctup);167        ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));168        LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));169    }170    {171        using Tuple = std::pair<int, NothrowMoveable>;172        Tuple tup; ((void)tup);173        Tuple const& ctup = tup; ((void)ctup);174        ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(ctup));175        LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(std::move(tup)));176    }177    {178        using Tuple = std::tuple<int, int, int>;179        Tuple tup; ((void)tup);180        ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));181    }182    {183        using Tuple = std::tuple<long, long, long>;184        Tuple tup; ((void)tup);185        LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));186    }187    {188        using Tuple = std::array<int, 3>;189        Tuple tup; ((void)tup);190        ASSERT_NOT_NOEXCEPT(std::make_from_tuple<TestType>(tup));191    }192    {193        using Tuple = std::array<long, 3>;194        Tuple tup; ((void)tup);195        LIBCPP_ASSERT_NOEXCEPT(std::make_from_tuple<TestType>(tup));196    }197}198 199namespace LWG3528 {200template <class T, class Tuple>201auto test_make_from_tuple(T&&, Tuple&& t) -> decltype(std::make_from_tuple<T>(t), std::uint8_t()) {202  return 0;203}204template <class T, class Tuple>205uint32_t test_make_from_tuple(...) {206  return 0;207}208 209template <class T, class Tuple>210static constexpr bool can_make_from_tuple =211    std::is_same_v<decltype(test_make_from_tuple<T, Tuple>(T{}, Tuple{})), std::uint8_t>;212 213#ifdef _LIBCPP_VERSION214template <class T, class Tuple>215auto test_make_from_tuple_impl(T&&, Tuple&& t)216    -> decltype(std::__make_from_tuple_impl<T>(217                    t, typename std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>()),218                std::uint8_t()) {219  return 0;220}221template <class T, class Tuple>222uint32_t test_make_from_tuple_impl(...) {223  return 0;224}225 226template <class T, class Tuple>227static constexpr bool can_make_from_tuple_impl =228    std::is_same_v<decltype(test_make_from_tuple_impl<T, Tuple>(T{}, Tuple{})), std::uint8_t>;229#endif // _LIBCPP_VERSION230 231struct A {232  int a;233};234struct B : public A {};235 236struct C {237  C(const B&) {}238};239 240enum class D {241  ONE,242  TWO,243};244 245// Test std::make_from_tuple constraints.246 247// reinterpret_cast248static_assert(!can_make_from_tuple<int*, std::tuple<A*>>);249static_assert(can_make_from_tuple<A*, std::tuple<A*>>);250 251// const_cast252static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>);253static_assert(!can_make_from_tuple<volatile char*, std::tuple<const volatile char*>>);254static_assert(can_make_from_tuple<volatile char*, std::tuple<volatile char*>>);255static_assert(can_make_from_tuple<char*, std::tuple<char*>>);256static_assert(can_make_from_tuple<const char*, std::tuple<char*>>);257static_assert(can_make_from_tuple<const volatile char*, std::tuple<volatile char*>>);258 259// static_cast260static_assert(!can_make_from_tuple<int, std::tuple<D>>);261static_assert(!can_make_from_tuple<D, std::tuple<int>>);262static_assert(can_make_from_tuple<long, std::tuple<int>>);263static_assert(can_make_from_tuple<double, std::tuple<float>>);264static_assert(can_make_from_tuple<float, std::tuple<double>>);265 266// Test std::__make_from_tuple_impl constraints.267 268// reinterpret_cast269LIBCPP_STATIC_ASSERT(!can_make_from_tuple_impl<int*, std::tuple<A*>>);270LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<A*, std::tuple<A*>>);271 272// const_cast273LIBCPP_STATIC_ASSERT(!can_make_from_tuple_impl<char*, std::tuple<const char*>>);274LIBCPP_STATIC_ASSERT(!can_make_from_tuple_impl<volatile char*, std::tuple<const volatile char*>>);275LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<volatile char*, std::tuple<volatile char*>>);276LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<char*, std::tuple<char*>>);277LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<const char*, std::tuple<char*>>);278LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<const volatile char*, std::tuple<volatile char*>>);279 280// static_cast281LIBCPP_STATIC_ASSERT(!can_make_from_tuple_impl<int, std::tuple<D>>);282LIBCPP_STATIC_ASSERT(!can_make_from_tuple_impl<D, std::tuple<int>>);283LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<long, std::tuple<int>>);284LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<double, std::tuple<float>>);285LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<float, std::tuple<double>>);286 287} // namespace LWG3528288 289static_assert(LWG3528::can_make_from_tuple<int, std::tuple<>>);290 291int main(int, char**)292{293    test_constexpr_construction();294    test_perfect_forwarding();295    test_noexcept();296 297  return 0;298}299