Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libcxx] adds concept
std::common_reference_with
Implements parts of: - P0898R3 Standard Library Concepts - P1754 Rename concepts to standard_case for C++20, while we still can Depends on D96657 Reviewed By: ldionne, Mordante, #libc Differential Revision: https://reviews.llvm.org/D96660
- Loading branch information
Showing
2 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
345 changes: 345 additions & 0 deletions
345
libcxx/test/std/concepts/lang/commonreference.compile.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,345 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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; } |