brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 8e3cad7 Raw
229 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++14, c++1710 11// type_traits12// common_reference13 14#include <tuple>15#include <type_traits>16#include <utility>17 18#include "test_macros.h"19 20template <class T>21constexpr bool has_type = requires { typename T::type; };22 23// A slightly simplified variation of std::tuple24template <class...>25struct UserTuple {};26 27template <class, class, class>28struct Tuple_helper {};29template <class... Ts, class... Us>30struct Tuple_helper<std::void_t<std::common_reference_t<Ts, Us>...>, UserTuple<Ts...>, UserTuple<Us...> > {31  using type = UserTuple<std::common_reference_t<Ts, Us>...>;32};33 34template <class... Ts, class... Us, template <class> class TQual, template <class> class UQual>35struct std::basic_common_reference< ::UserTuple<Ts...>, ::UserTuple<Us...>, TQual, UQual>36    : ::Tuple_helper<void, UserTuple<TQual<Ts>...>, UserTuple<UQual<Us>...> > {};37 38struct X2 {};39struct Y2 {};40struct Z2 {};41 42template <>43struct std::common_type<X2, Y2> {44  using type = Z2;45};46template <>47struct std::common_type<Y2, X2> {48  using type = Z2;49};50 51// (6.1)52//  -- If sizeof...(T) is zero, there shall be no member type.53static_assert(!has_type<std::common_reference<> >);54 55// (6.2)56//  -- Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the57//     pack T. The member typedef type shall denote the same type as T0.58static_assert(std::is_same_v<std::common_reference_t<void>, void>);59static_assert(std::is_same_v<std::common_reference_t<int>, int>);60static_assert(std::is_same_v<std::common_reference_t<int&>, int&>);61static_assert(std::is_same_v<std::common_reference_t<int&&>, int&&>);62static_assert(std::is_same_v<std::common_reference_t<int const>, int const>);63static_assert(std::is_same_v<std::common_reference_t<int const&>, int const&>);64static_assert(std::is_same_v<std::common_reference_t<int const&&>, int const&&>);65static_assert(std::is_same_v<std::common_reference_t<int volatile[]>, int volatile[]>);66static_assert(std::is_same_v<std::common_reference_t<int volatile (&)[]>, int volatile (&)[]>);67static_assert(std::is_same_v<std::common_reference_t<int volatile (&&)[]>, int volatile (&&)[]>);68static_assert(std::is_same_v<std::common_reference_t<void (&)()>, void (&)()>);69static_assert(std::is_same_v<std::common_reference_t<void (&&)()>, void (&&)()>);70 71// (6.3)72//  -- Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in73//     the pack T. Then74// (6.3.1)75//    -- Let R be COMMON-REF(T1, T2). If T1 and T2 are reference types, R is well-formed,76//       and is_convertible_v<add_pointer_t<T1>, add_pointer_t<R>> && is_convertible_v<add_pointer_t<T2>, add_pointer_t<R>>77//       is true, then the member typedef type denotes R.78 79struct B {};80struct D : B {};81static_assert(std::is_same_v<std::common_reference_t<B&, D&>, B&>);82static_assert(std::is_same_v<std::common_reference_t<B const&, D&>, B const&>);83static_assert(std::is_same_v<std::common_reference_t<B&, D const&>, B const&>);84static_assert(std::is_same_v<std::common_reference_t<B&, D const&, D&>, B const&>);85static_assert(std::is_same_v<std::common_reference_t<B&, D&, B&, D&>, B&>);86 87static_assert(std::is_same_v<std::common_reference_t<B&&, D&&>, B&&>);88static_assert(std::is_same_v<std::common_reference_t<B const&&, D&&>, B const&&>);89static_assert(std::is_same_v<std::common_reference_t<B&&, D const&&>, B const&&>);90static_assert(std::is_same_v<std::common_reference_t<B&, D&&>, B const&>);91static_assert(std::is_same_v<std::common_reference_t<B&, D const&&>, B const&>);92static_assert(std::is_same_v<std::common_reference_t<B const&, D&&>, B const&>);93 94static_assert(std::is_same_v<std::common_reference_t<B&&, D&>, B const&>);95static_assert(std::is_same_v<std::common_reference_t<B&&, D const&>, B const&>);96static_assert(std::is_same_v<std::common_reference_t<B const&&, D&>, B const&>);97 98static_assert(std::is_same_v<std::common_reference_t<int const&, int volatile&>, int const volatile&>);99static_assert(std::is_same_v<std::common_reference_t<int const volatile&&, int volatile&&>, int const volatile&&>);100 101static_assert(std::is_same_v<std::common_reference_t<int (&)[10], int (&&)[10]>, int const (&)[10]>);102static_assert(103    std::is_same_v<std::common_reference_t<int const (&)[10], int volatile (&)[10]>, int const volatile (&)[10]>);104 105// when conversion from pointers are not true106struct E {};107struct F {108  operator E&() const;109};110 111static_assert(!std::is_convertible_v<F*, E*>);112 113// The following should not use 6.3.1, but fallback to 6.3.3114static_assert(std::is_same_v<std::common_reference_t<E&, F>, E&>);115 116// (6.3.2)117//    -- Otherwise, if basic_common_reference<remove_cvref_t<T1>,118//       remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type is well-formed, then the119//       member typedef type denotes that type.120static_assert(std::is_same_v<std::common_reference_t<const UserTuple<int, short>&, UserTuple<int&, short volatile&>>,121                             UserTuple<const int&, const volatile short&>>);122 123static_assert(std::is_same_v<std::common_reference_t<volatile UserTuple<int, short>&, const UserTuple<int, short>&>,124                             const volatile UserTuple<int, short>&>);125 126// (6.3.3)127//    -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef128//       type denotes that type.129static_assert(std::is_same_v<std::common_reference_t<void, void>, void>);130static_assert(std::is_same_v<std::common_reference_t<int, short>, int>);131static_assert(std::is_same_v<std::common_reference_t<int, short&>, int>);132static_assert(std::is_same_v<std::common_reference_t<int&, short&>, int>);133static_assert(std::is_same_v<std::common_reference_t<int&, short>, int>);134 135// tricky volatile reference case136static_assert(std::is_same_v<std::common_reference_t<int&&, int volatile&>, int>);137static_assert(std::is_same_v<std::common_reference_t<int volatile&, int&&>, int>);138 139static_assert(std::is_same_v<std::common_reference_t<int (&)[10], int (&)[11]>, int*>);140 141// https://github.com/ericniebler/stl2/issues/338142struct MyIntRef {143  MyIntRef(int&);144};145static_assert(std::is_same_v<std::common_reference_t<int&, MyIntRef>, MyIntRef>);146 147// (6.3.4)148//    -- Otherwise, if common_type_t<T1, T2> is well-formed, then the member149//       typedef type denotes that type.150struct moveonly {151  moveonly()                      = default;152  moveonly(moveonly&&)            = default;153  moveonly& operator=(moveonly&&) = default;154};155struct moveonly2 : moveonly {};156 157static_assert(std::is_same_v<std::common_reference_t<moveonly const&, moveonly>, moveonly>);158static_assert(std::is_same_v<std::common_reference_t<moveonly2 const&, moveonly>, moveonly>);159static_assert(std::is_same_v<std::common_reference_t<moveonly const&, moveonly2>, moveonly>);160 161static_assert(std::is_same_v<std::common_reference_t<X2&, Y2 const&>, Z2>);162 163// (6.3.5)164//    -- Otherwise, there shall be no member type.165static_assert(!has_type<std::common_reference<volatile UserTuple<short>&, const UserTuple<int, short>&> >);166 167// (6.4)168//  -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest,169//     respectively, denote the first, second, and (pack of) remaining types170//     comprising T. Let C be the type common_reference_t<T1, T2>. Then:171// (6.4.1)172//    -- If there is such a type C, the member typedef type shall denote the173//       same type, if any, as common_reference_t<C, Rest...>.174static_assert(std::is_same_v<std::common_reference_t<int, int, int>, int>);175static_assert(std::is_same_v<std::common_reference_t<int&&, int const&, int volatile&>, int const volatile&>);176static_assert(std::is_same_v<std::common_reference_t<int&&, int const&, float&>, float>);177 178// (6.4.2)179//    -- Otherwise, there shall be no member type.180static_assert(!has_type<std::common_reference<int, short, int, char*> >);181 182#if TEST_STD_VER > 20183static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, int>>, std::tuple<int, int>>);184static_assert(185    std::is_same_v<std::common_reference_t<std::tuple<int, long>, std::tuple<long, int>>, std::tuple<long, long>>);186static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, const int&>, std::tuple<const int&, int>>,187                             std::tuple<const int&, int>>);188static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, volatile int&>, std::tuple<volatile int&, int>>,189                             std::tuple<volatile int&, int>>);190static_assert(191    std::is_same_v<std::common_reference_t<std::tuple<int&, const volatile int&>, std::tuple<const volatile int&, int>>,192                   std::tuple<const volatile int&, int>>);193static_assert(194    !has_type<std::common_reference_t<std::tuple<const int&, volatile int&>, std::tuple<volatile int&, const int&>>>);195 196static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);197static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);198static_assert(!has_type<std::common_reference<std::tuple<int, const X2>, std::tuple<float, const Z2>>>);199static_assert(!has_type<std::common_reference<std::tuple<int, X2>, std::tuple<float, Z2>>>);200static_assert(!has_type<std::common_reference<std::tuple<int, X2>, int, X2>>);201 202struct A {};203template <template <class> class TQual, template <class> class UQual>204struct std::basic_common_reference<A, std::tuple<B>, TQual, UQual> {205  using type = tuple<UQual<B>>;206};207 208static_assert(std::is_same_v<std::common_reference_t<A, std::tuple<B>, std::tuple<D>>, std::tuple<B>>);209 210static_assert(std::is_same_v<std::common_reference_t<std::pair<int, int>>, std::pair<int, int>>);211static_assert(212    std::is_same_v<std::common_reference_t<std::pair<int, long>, std::pair<long, int>>, std::pair<long, long>>);213static_assert(std::is_same_v<std::common_reference_t<std::pair<int&, const int&>, std::pair<const int&, int>>,214                             std::pair<const int&, int>>);215static_assert(std::is_same_v<std::common_reference_t<std::pair<int&, volatile int&>, std::pair<volatile int&, int>>,216                             std::pair<volatile int&, int>>);217static_assert(218    std::is_same_v<std::common_reference_t<std::pair<int&, const volatile int&>, std::pair<const volatile int&, int>>,219                   std::pair<const volatile int&, int>>);220static_assert(221    !has_type<std::common_reference_t<std::pair<const int&, volatile int&>, std::pair<volatile int&, const int&>>>);222 223static_assert(std::is_same_v<std::common_reference_t<std::pair<int, X2>, std::pair<int, Y2>>, std::pair<int, Z2>>);224static_assert(std::is_same_v<std::common_reference_t<std::pair<int, X2>, std::pair<int, Y2>>, std::pair<int, Z2>>);225static_assert(!has_type<std::common_reference<std::pair<int, const X2>, std::pair<float, const Z2>>>);226static_assert(!has_type<std::common_reference<std::pair<int, X2>, std::pair<float, Z2>>>);227static_assert(!has_type<std::common_reference<std::pair<int, X2>, int, X2>>);228#endif229