346 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
// UNSUPPORTED: c++03, c++11, c++14, c++17
 | 
						|
// UNSUPPORTED: libcpp-no-concepts
 | 
						|
 | 
						|
// template<class From, class To>
 | 
						|
// concept common_reference_with;
 | 
						|
 | 
						|
#include <concepts>
 | 
						|
 | 
						|
template <class T, class U>
 | 
						|
constexpr bool CheckCommonReferenceWith() noexcept {
 | 
						|
  static_assert(std::common_reference_with<T, U&>);
 | 
						|
  static_assert(std::common_reference_with<T, const U&>);
 | 
						|
  static_assert(std::common_reference_with<T, volatile U&>);
 | 
						|
  static_assert(std::common_reference_with<T, const volatile U&>);
 | 
						|
  static_assert(std::common_reference_with<T, U&&>);
 | 
						|
  static_assert(std::common_reference_with<T, const U&&>);
 | 
						|
  static_assert(std::common_reference_with<T, volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<T, const volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<T&, U&&>);
 | 
						|
  static_assert(std::common_reference_with<T&, const U&&>);
 | 
						|
  static_assert(std::common_reference_with<T&, volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<T&, const volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<const T&, U&&>);
 | 
						|
  static_assert(std::common_reference_with<const T&, const U&&>);
 | 
						|
  static_assert(std::common_reference_with<const T&, volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<const T&, const volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<volatile T&, U&&>);
 | 
						|
  static_assert(std::common_reference_with<volatile T&, const U&&>);
 | 
						|
  static_assert(std::common_reference_with<volatile T&, volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<volatile T&, const volatile U&&>);
 | 
						|
  static_assert(std::common_reference_with<const volatile T&, U&&>);
 | 
						|
  static_assert(std::common_reference_with<const volatile T&, const U&&>);
 | 
						|
  static_assert(std::common_reference_with<const volatile T&, volatile U&&>);
 | 
						|
  static_assert(
 | 
						|
      std::common_reference_with<const volatile T&, const volatile U&&>);
 | 
						|
 | 
						|
  return std::common_reference_with<T, U>;
 | 
						|
}
 | 
						|
 | 
						|
namespace BuiltinTypes {
 | 
						|
// fundamental types
 | 
						|
static_assert(std::common_reference_with<void, void>);
 | 
						|
static_assert(CheckCommonReferenceWith<int, int>());
 | 
						|
static_assert(CheckCommonReferenceWith<int, long>());
 | 
						|
static_assert(CheckCommonReferenceWith<int, unsigned char>());
 | 
						|
#ifndef _LIBCPP_HAS_NO_INT128
 | 
						|
static_assert(CheckCommonReferenceWith<int, __int128_t>());
 | 
						|
#endif
 | 
						|
static_assert(CheckCommonReferenceWith<int, double>());
 | 
						|
 | 
						|
// arrays
 | 
						|
static_assert(CheckCommonReferenceWith<int[5], int[5]>());
 | 
						|
 | 
						|
// pointers (common with void*)
 | 
						|
static_assert(CheckCommonReferenceWith<int*, void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<int*, const void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<int*, volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<int*, const volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const int*, void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const int*, const void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const int*, volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const int*, const volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<volatile int*, void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<volatile int*, const void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<volatile int*, volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<volatile int*, const volatile void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const volatile int*, void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const volatile int*, const void*>());
 | 
						|
static_assert(CheckCommonReferenceWith<const volatile int*, volatile void*>());
 | 
						|
static_assert(
 | 
						|
    CheckCommonReferenceWith<const volatile int*, const volatile void*>());
 | 
						|
 | 
						|
static_assert(CheckCommonReferenceWith<int (*)(), int (*)()>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (*)(), int (*)() noexcept>());
 | 
						|
struct S {};
 | 
						|
static_assert(CheckCommonReferenceWith<int S::*, int S::*>());
 | 
						|
static_assert(CheckCommonReferenceWith<int S::*, const int S::*>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)(), int (S::*)()>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)(), int (S::*)() noexcept>());
 | 
						|
static_assert(
 | 
						|
    CheckCommonReferenceWith<int (S::*)() const, int (S::*)() const>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)() const,
 | 
						|
                                       int (S::*)() const noexcept>());
 | 
						|
static_assert(
 | 
						|
    CheckCommonReferenceWith<int (S::*)() volatile, int (S::*)() volatile>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)() volatile,
 | 
						|
                                       int (S::*)() volatile noexcept>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)() const volatile,
 | 
						|
                                       int (S::*)() const volatile>());
 | 
						|
static_assert(CheckCommonReferenceWith<int (S::*)() const volatile,
 | 
						|
                                       int (S::*)() const volatile noexcept>());
 | 
						|
 | 
						|
// nonsense
 | 
						|
static_assert(!std::common_reference_with<double, float*>);
 | 
						|
static_assert(!std::common_reference_with<int, int[5]>);
 | 
						|
static_assert(!std::common_reference_with<int*, long*>);
 | 
						|
static_assert(!std::common_reference_with<int*, unsigned int*>);
 | 
						|
static_assert(!std::common_reference_with<int (*)(), int (*)(int)>);
 | 
						|
static_assert(!std::common_reference_with<int S::*, float S::*>);
 | 
						|
static_assert(!std::common_reference_with<int (S::*)(), int (S::*)() const>);
 | 
						|
static_assert(!std::common_reference_with<int (S::*)(), int (S::*)() volatile>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<int (S::*)(), int (S::*)() const volatile>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<int (S::*)() const, int (S::*)() volatile>);
 | 
						|
static_assert(!std::common_reference_with<int (S::*)() const,
 | 
						|
                                          int (S::*)() const volatile>);
 | 
						|
static_assert(!std::common_reference_with<int (S::*)() volatile,
 | 
						|
                                          int (S::*)() const volatile>);
 | 
						|
} // namespace BuiltinTypes
 | 
						|
 | 
						|
namespace NoDefaultCommonReference {
 | 
						|
class T {};
 | 
						|
 | 
						|
static_assert(!std::common_reference_with<T, int>);
 | 
						|
static_assert(!std::common_reference_with<int, T>);
 | 
						|
static_assert(!std::common_reference_with<T, int[10]>);
 | 
						|
static_assert(!std::common_reference_with<T[10], int>);
 | 
						|
static_assert(!std::common_reference_with<T*, int*>);
 | 
						|
static_assert(!std::common_reference_with<T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, int*>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T*, int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T*, volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T*, const int*>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T*, volatile int*>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<const T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<volatile T*, const volatile int*>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T*, const volatile int*>);
 | 
						|
static_assert(!std::common_reference_with<T&, int&>);
 | 
						|
static_assert(!std::common_reference_with<T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, volatile int&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const volatile int&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<T&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&, volatile int&&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&, const volatile int&&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, int&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, const int&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, volatile int&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const volatile int&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&&, const volatile int&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<T&&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, const int&&>);
 | 
						|
static_assert(!std::common_reference_with<const volatile T&&, volatile int&&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<const T&&, const volatile int&&>);
 | 
						|
static_assert(!std::common_reference_with<volatile T&&, const volatile int&&>);
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<const volatile T&&, const volatile int&&>);
 | 
						|
} // namespace NoDefaultCommonReference
 | 
						|
 | 
						|
struct BadBasicCommonReference {
 | 
						|
  // This test is ill-formed, NDR. If it ever blows up in our faces: that's a good thing.
 | 
						|
  // In the meantime, the test should be included. If compiler support is added, then an include guard
 | 
						|
  // should be placed so the test doesn't get deleted.
 | 
						|
  operator int() const;
 | 
						|
  operator int&();
 | 
						|
};
 | 
						|
static_assert(std::convertible_to<BadBasicCommonReference, int>);
 | 
						|
static_assert(std::convertible_to<BadBasicCommonReference, int&>);
 | 
						|
 | 
						|
namespace std {
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<BadBasicCommonReference, int, X, Y> {
 | 
						|
  using type = BadBasicCommonReference&;
 | 
						|
};
 | 
						|
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<int, BadBasicCommonReference, X, Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
} // namespace std
 | 
						|
static_assert(!std::common_reference_with<BadBasicCommonReference, int>);
 | 
						|
 | 
						|
struct StructNotConvertibleToCommonReference {
 | 
						|
  explicit(false) StructNotConvertibleToCommonReference(int);
 | 
						|
};
 | 
						|
static_assert(std::convertible_to<int, StructNotConvertibleToCommonReference>);
 | 
						|
 | 
						|
namespace std {
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<StructNotConvertibleToCommonReference, int, X,
 | 
						|
                              Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<int, StructNotConvertibleToCommonReference, X,
 | 
						|
                              Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
} // namespace std
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<StructNotConvertibleToCommonReference, int>);
 | 
						|
 | 
						|
struct IntNotConvertibleToCommonReference {
 | 
						|
  operator int&() const;
 | 
						|
};
 | 
						|
 | 
						|
namespace std {
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<IntNotConvertibleToCommonReference, int, X, Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<int, IntNotConvertibleToCommonReference, X, Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
} // namespace std
 | 
						|
static_assert(
 | 
						|
    !std::common_reference_with<StructNotConvertibleToCommonReference, int>);
 | 
						|
 | 
						|
struct HasCommonReference {
 | 
						|
  explicit(false) HasCommonReference(int);
 | 
						|
  operator int&() const;
 | 
						|
};
 | 
						|
 | 
						|
namespace std {
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<HasCommonReference, int, X, Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
 | 
						|
template <template <class> class X, template <class> class Y>
 | 
						|
struct basic_common_reference<int, HasCommonReference, X, Y> {
 | 
						|
  using type = int&;
 | 
						|
};
 | 
						|
} // namespace std
 | 
						|
static_assert(!std::common_reference_with<HasCommonReference, int>);
 | 
						|
static_assert(std::common_reference_with<HasCommonReference, int&>);
 | 
						|
 | 
						|
int main(int, char**) { return 0; }
 |