blob: f2fafec4666041ba0669ce18650dcaab249dacc4 [file] [log] [blame]
// P2655R3 - common_reference_t of reference_wrapper Should Be a Reference Type
// Implemented as a DR against C++20
// { dg-do compile { target c++20 } }
#include <functional>
#if __cpp_lib_common_reference_wrapper != 202302L
# error "Feature-test macro __cpp_lib_common_reference_wrapper has wrong value in <functional>"
#endif
using std::is_same_v;
using std::common_reference_t;
using std::reference_wrapper;
static_assert( is_same_v<common_reference_t<const reference_wrapper<int>&, int&>, int&> );
static_assert( is_same_v<common_reference_t<int&, const reference_wrapper<int>&>, int&> );
static_assert( is_same_v<common_reference_t<reference_wrapper<int>, int&>,
common_reference_t<int&, int&>> );
static_assert( is_same_v<common_reference_t<reference_wrapper<int>, const int&>,
common_reference_t<int&, const int&>> );
static_assert( is_same_v<common_reference_t<reference_wrapper<const int>, int&>,
common_reference_t<const int&, int&>> );
static_assert( is_same_v<common_reference_t<int&, reference_wrapper<int>>,
common_reference_t<int&, int&>> );
static_assert( is_same_v<common_reference_t<const int&, reference_wrapper<int>>,
common_reference_t<int&, const int&>> );
static_assert( is_same_v<common_reference_t<int&, reference_wrapper<const int>>,
common_reference_t<const int&, int&>> );
static_assert( is_same_v<common_reference_t<reference_wrapper<int>&, reference_wrapper<int>&>,
reference_wrapper<int>&> );
static_assert( is_same_v<common_reference_t<reference_wrapper<char>,
reference_wrapper<int>>,
int> );
static_assert( is_same_v<common_reference_t<reference_wrapper<reference_wrapper<int>>,
reference_wrapper<int>>,
reference_wrapper<int>> );
static_assert( is_same_v<common_reference_t<reference_wrapper<int>,
reference_wrapper<reference_wrapper<int>>>,
reference_wrapper<int>> );
struct A { };
struct B { operator A&() const; };
template<typename T, typename U>
concept has_common_reference = requires {
typename std::common_reference_t<T, U>;
};
static_assert( is_same_v<common_reference_t<reference_wrapper<A>, const B&>, A&> );
// reference_wrapper<const B> is not convertible to A&, as it would require two user
// defined conversions.
static_assert( !has_common_reference<A, reference_wrapper<const B>> );
static_assert( !has_common_reference<reference_wrapper<A>, reference_wrapper<const B>> );
struct D1 : A {};
struct D2 : A {};
template<template<class> typename Qual1, template<class> typename Qual2>
struct std::basic_common_reference<D1, D2, Qual1, Qual2>
: std::common_reference<Qual1<A>, Qual2<A>>
{ };
template<template<class> typename Qual1, template<class> typename Qual2>
struct std::basic_common_reference<D2, D1, Qual1, Qual2>
: std::common_reference<Qual1<A>, Qual2<A>>
{ };
static_assert( is_same_v<common_reference_t<D1&, D2&>, A&> );
static_assert( is_same_v<common_reference_t<reference_wrapper<D1>, D2&>, A&> );
static_assert( is_same_v<common_reference_t<D1&, reference_wrapper<D2>>, A&> );
static_assert( !has_common_reference<reference_wrapper<D1>, reference_wrapper<D2>> );