brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · a3630cb Raw
153 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// <functional>10//11// UNSUPPORTED: c++03, c++11, c++14, c++1712//13// common_reference specializations for reference_wrapper14 15#include <concepts>16#include <functional>17#include <type_traits>18 19template <class T>20concept HasType = requires { typename T::type; };21 22template <class Result, class T1, class T2>23concept check_XY = std::same_as<Result, std::common_reference_t<T1, T2>>;24 25template <class Result, class T1, class T2>26concept check_YX = std::same_as<Result, std::common_reference_t<T2, T1>>;27 28template <class Result, class T1, class T2>29concept check = check_XY<Result, T1, T2> && check_YX<Result, T1, T2>;30 31template <class T1, class T2>32concept check_none_XY = !HasType<std::common_reference<T1, T2>>;33template <class T1, class T2>34concept check_none_YX = !HasType<std::common_reference<T2, T1>>;35 36template <class T1, class T2>37concept check_none = check_none_XY<T1, T2> && check_none_YX<T1, T2>;38 39// https://eel.is/c++draft/meta.trans#other-2.440template <class X, class Y>41using CondRes = decltype(false ? std::declval<X (&)()>()() : std::declval<Y (&)()>()());42 43template <class X, class Y>44struct Ternary {};45 46template <class X, class Y>47  requires requires() { typename CondRes<X, Y>; }48struct Ternary<X, Y> {49  using type = CondRes<X, Y>;50};51template <class X, class Y>52using Ternary_t = typename Ternary<X, Y>::type;53 54template <class T>55using Ref = std::reference_wrapper<T>;56 57using std::common_reference_t;58using std::same_as;59 60// clang-format off61static_assert(check<int &     , Ref<int      >, int &      >);62static_assert(check<int const&, Ref<int      >, int const& >);63static_assert(check<int const&, Ref<int const>, int &      >);64static_assert(check<int const&, Ref<int const>, int const& >);65static_assert(check<int&,       Ref<int> const&, int& >);66static_assert(check<const volatile int&, Ref<const volatile int>, const volatile int&>);67 68// derived-base and implicit convertibles69struct B {};70struct D : B {};71struct C {72    operator B&() const;73};74 75static_assert(check<B&      , Ref<B>,       D &     >);76static_assert(check<B const&, Ref<B>,       D const&>);77static_assert(check<B const&, Ref<B const>, D const&>);78 79static_assert(check<B&      , Ref<D>,       B &     >);80static_assert(check<B const&, Ref<D>,       B const&>);81static_assert(check<B const&, Ref<D const>, B const&>);82 83static_assert(std::same_as<B&,       CondRes<Ref<D>,       B&>>);84static_assert(std::same_as<B const&, CondRes<Ref<D>,       B const &>>);85static_assert(std::same_as<B const&, CondRes<Ref<D const>, B const&>>);86 87static_assert( check<B&        , Ref<B>      , C&      >);88static_assert( check<B&        , Ref<B>      , C       >);89static_assert( check<B const&  , Ref<B const>, C       >);90static_assert(!check<B&        , Ref<C>      , B&      >); // Ref<C> cannot be converted to B&91static_assert( check<B&        , Ref<B>      , C const&>); // was const B& before P2655R392 93 94using Ri   = Ref<int>;95using RRi  = Ref<Ref<int>>;96using RRRi = Ref<Ref<Ref<int>>>;97static_assert(check<Ri&,  Ri&,  RRi>);98static_assert(check<RRi&, RRi&, RRRi>);99static_assert(check<Ri,   Ri,   RRi>);100static_assert(check<RRi,  RRi,  RRRi>);101 102static_assert(check_none<int&, RRi>);103static_assert(check_none<int,  RRi>);104static_assert(check_none<int&, RRRi>);105static_assert(check_none<int,  RRRi>);106 107static_assert(check_none<Ri&, RRRi>);108static_assert(check_none<Ri,  RRRi>);109 110 111template <typename T>112struct Test {113  // Check that reference_wrapper<T> behaves the same as T& in common_reference.114 115  using R1 = common_reference_t<T&, T&>;116  using R2 = common_reference_t<T&, T const&>;117  using R3 = common_reference_t<T&, T&&>;118  using R4 = common_reference_t<T&, T const&&>;119  using R5 = common_reference_t<T&, T>;120 121  static_assert(same_as<R1, common_reference_t<Ref<T>, T&>>);122  static_assert(same_as<R2, common_reference_t<Ref<T>, T const&>>);123  static_assert(same_as<R3, common_reference_t<Ref<T>, T&&>>);124  static_assert(same_as<R4, common_reference_t<Ref<T>, T const&&>>);125  static_assert(same_as<R5, common_reference_t<Ref<T>, T>>);126 127  // commute:128  static_assert(same_as<R1, common_reference_t<T&,        Ref<T>>>);129  static_assert(same_as<R2, common_reference_t<T const&,  Ref<T>>>);130  static_assert(same_as<R3, common_reference_t<T&&,       Ref<T>>>);131  static_assert(same_as<R4, common_reference_t<T const&&, Ref<T>>>);132  static_assert(same_as<R5, common_reference_t<T,         Ref<T>>>);133 134  // reference qualification of reference_wrapper is irrelevant 135  static_assert(same_as<R1, common_reference_t<Ref<T>&,        T&>>);136  static_assert(same_as<R1, common_reference_t<Ref<T> ,        T&>>);137  static_assert(same_as<R1, common_reference_t<Ref<T> const&,  T&>>);138  static_assert(same_as<R1, common_reference_t<Ref<T>&&,       T&>>);139  static_assert(same_as<R1, common_reference_t<Ref<T> const&&, T&>>);140};141 142// clang-format on143// Instantiate above checks:144template struct Test<int>;145template struct Test<std::reference_wrapper<int>>;146 147// reference_wrapper as both args is unaffected.148// subject to simple first rule of149static_assert(check<Ref<int>&, Ref<int>&, Ref<int>&>);150 151// double wrap is unaffected.152static_assert(check<Ref<int>&, Ref<Ref<int>>, Ref<int>&>);153