forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc++] Forbid default_delete<Derived> to convert to default_delete<…
…NonVirtualBase> Per an idea by Lénárd Szolnoki. In 2023, Peter Sommerlad was considering proposing this to WG21. Also, implement `is_similar_v`.
- Loading branch information
1 parent
6f67efe
commit 064121a
Showing
8 changed files
with
268 additions
and
1 deletion.
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
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
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
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,60 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___TYPE_TRAITS_IS_SIMILAR_H | ||
| #define _LIBCPP___TYPE_TRAITS_IS_SIMILAR_H | ||
|
|
||
| #include <__config> | ||
| #include <__type_traits/conditional.h> | ||
| #include <__type_traits/integral_constant.h> | ||
| #include <__type_traits/is_const.h> | ||
| #include <__type_traits/is_same.h> | ||
| #include <__type_traits/is_volatile.h> | ||
| #include <__type_traits/remove_cv.h> | ||
| #include <cstddef> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| _LIBCPP_BEGIN_NAMESPACE_STD | ||
|
|
||
| template <class _Tp, class _Up> | ||
| struct is_similar : conditional< | ||
| is_const<_Tp>::value || is_volatile<_Tp>::value || | ||
| is_const<_Up>::value || is_volatile<_Up>::value, | ||
| is_similar<typename remove_cv<_Tp>::type, typename remove_cv<_Up>::type>, | ||
| is_same<_Tp, _Up> | ||
| >::type {}; | ||
|
|
||
| template <class _Tp, class _Up> | ||
| struct is_similar<_Tp*, _Up*>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| template <class _Tp, class _Up, class _Cp> | ||
| struct is_similar<_Tp _Cp::*, _Up _Cp::*>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| template <class _Tp, class _Up> | ||
| struct is_similar<_Tp[], _Up[]>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| template <class _Tp, class _Up, size_t _Np> | ||
| struct is_similar<_Tp[], _Up[_Np]>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| template <class _Tp, class _Up, size_t _Np> | ||
| struct is_similar<_Tp[_Np], _Up[]>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| template <class _Tp, class _Up, size_t _Np> | ||
| struct is_similar<_Tp[_Np], _Up[_Np]>: is_similar<_Tp, _Up> {}; | ||
|
|
||
| #if _LIBCPP_STD_VER > 14 | ||
| template <class _Tp, class _Up> | ||
| inline constexpr bool is_similar_v = is_similar<_Tp, _Up>::value; | ||
| #endif | ||
|
|
||
| _LIBCPP_END_NAMESPACE_STD | ||
|
|
||
| #endif // _LIBCPP___TYPE_TRAITS_IS_SIMILAR_H |
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
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
120 changes: 120 additions & 0 deletions
120
libcxx/test/std/concepts/concepts.lang/concept.same/similar_to.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,120 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 T, class U> | ||
| // concept similar_to; | ||
|
|
||
| #include <concepts> | ||
| #include <type_traits> | ||
|
|
||
| struct S; | ||
|
|
||
| void CheckSimilarTo() { | ||
| static_assert(std::similar_to<int, int>); | ||
| static_assert(std::similar_to<int*, int*>); | ||
| static_assert(std::similar_to<int[], int[]>); | ||
| static_assert(std::similar_to<int[9], int[]>); | ||
| static_assert(std::similar_to<int[], int[9]>); | ||
| static_assert(std::similar_to<int[9], int[9]>); | ||
|
|
||
| static_assert(std::similar_to<const int, int>); | ||
| static_assert(std::similar_to<int const*, int*>); | ||
| static_assert(std::similar_to<int *const, int*>); | ||
| static_assert(std::similar_to<int const[], int[]>); | ||
| static_assert(std::similar_to<int const[9], int[]>); | ||
| static_assert(std::similar_to<int const[], int[9]>); | ||
| static_assert(std::similar_to<int const[9], int[9]>); | ||
|
|
||
| static_assert(std::similar_to<int, const int>); | ||
| static_assert(std::similar_to<int*, int const*>); | ||
| static_assert(std::similar_to<int*, int *const>); | ||
| static_assert(std::similar_to<int[], int const[]>); | ||
| static_assert(std::similar_to<int[9], int const[]>); | ||
| static_assert(std::similar_to<int[], int const[9]>); | ||
| static_assert(std::similar_to<int[9], int const[9]>); | ||
|
|
||
| static_assert(!std::similar_to<int&, int>); | ||
| static_assert(!std::similar_to<int, int&>); | ||
| static_assert(!std::similar_to<int&&, int>); | ||
| static_assert(!std::similar_to<int, int&&>); | ||
| static_assert(!std::similar_to<int&&, int&>); | ||
| static_assert(!std::similar_to<int&, int&&>); | ||
|
|
||
| static_assert(std::similar_to<int S::*, int S::*>); | ||
| static_assert(std::similar_to<int& (S::*)(), int& (S::*)()>); | ||
| static_assert(std::similar_to<int& (S::*)(int*), int& (S::*)(int*)>); | ||
|
|
||
| static_assert(std::similar_to<int S::*, int S::*const>); | ||
| static_assert(std::similar_to<int& (S::*)(), int& (S::*const)()>); | ||
| static_assert(std::similar_to<int& (S::*)(int*), int& (S::*const)(int*)>); | ||
|
|
||
| static_assert(!std::similar_to<int S::*, char S::*>); | ||
| static_assert(!std::similar_to<int& (S::*)(), const int& (S::*)()>); | ||
| static_assert(!std::similar_to<int& (S::*)(), int (S::*)()>); | ||
| static_assert(!std::similar_to<int& (S::*)(), int (S::*)()>); | ||
| static_assert(!std::similar_to<int (S::*)(char), int (S::*)(int)>); | ||
| static_assert(!std::similar_to<int& (S::*)(int*), int& (S::*)(int const*)>); | ||
| } | ||
|
|
||
| void CheckFunctionTypes() { | ||
| static_assert(std::similar_to<int(), int()>); | ||
| static_assert(std::similar_to<int(int), int(int)>); | ||
| static_assert(std::similar_to<int(*)(int), int(*const)(int)>); | ||
|
|
||
| static_assert(!std::similar_to<int(), int(int)>); | ||
| static_assert(!std::similar_to<int(), void()>); | ||
| static_assert(!std::similar_to<int(), int(*)()>); | ||
| static_assert(!std::similar_to<int(int*), int(int const*)>); | ||
| static_assert(!std::similar_to<int*(), int const*()>); | ||
| } | ||
|
|
||
| void CheckArraysofUnknownBound() { | ||
| static_assert(std::similar_to<int[], int[9]>); | ||
| static_assert(std::similar_to<int[9], int[]>); | ||
| static_assert(std::similar_to<int(*)[], int(*)[9]>); | ||
| static_assert(std::similar_to<int(*)[9], int(*)[]>); | ||
| static_assert(std::similar_to<int(*)[], int(*const)[9]>); | ||
| static_assert(std::similar_to<int(*)[9], int(*const)[]>); | ||
| static_assert(std::similar_to<int(*const*)[], int(**)[9]>); | ||
| static_assert(std::similar_to<int(*const*)[9], int(**)[]>); | ||
| static_assert(std::similar_to<int *(*const*)[], int *const(**)[9]>); | ||
| static_assert(std::similar_to<int *(*const*)[9], int *const(**)[]>); | ||
|
|
||
| static_assert(!std::similar_to<int[9], int[10]>); | ||
| static_assert(!std::similar_to<int(*)[9], int(*)[10]>); | ||
| static_assert(!std::similar_to<int *(*const*)[9], int *const(**)[10]>); | ||
| } | ||
|
|
||
|
|
||
| template <class T, class U> requires std::same_as<T, U> | ||
| void SubsumptionTest1(); | ||
|
|
||
| template <class T, class U> requires std::similar_to<U, T> | ||
| int SubsumptionTest1(); | ||
|
|
||
| static_assert(std::same_as<void, decltype(SubsumptionTest1<int, int>())>); | ||
| static_assert(std::same_as<int, decltype(SubsumptionTest1<int, const int>())>); | ||
|
|
||
|
|
||
| template <class T, class U> requires std::similar_to<T, U> | ||
| void SubsumptionTest2(); | ||
|
|
||
| template <class T, class U> requires std::similar_to<U, T> && (sizeof(T) > 0) | ||
| int SubsumptionTest2(); | ||
|
|
||
| static_assert(std::same_as<int, decltype(SubsumptionTest2<int, int>())>); | ||
| static_assert(std::same_as<int, decltype(SubsumptionTest2<int, const int>())>); | ||
|
|
||
|
|
||
| int main(int, char**) { | ||
| CheckSimilarTo(); | ||
| return 0; | ||
| } |
67 changes: 67 additions & 0 deletions
67
libcxx/test/std/utilities/meta/meta.rel/is_similar.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,67 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // type_traits | ||
|
|
||
| // is_same | ||
|
|
||
| #include <type_traits> | ||
|
|
||
| struct S; | ||
|
|
||
| void CheckIsSimilar() { | ||
| static_assert(std::is_similar<int, int>::value, ""); | ||
| static_assert(std::is_similar<int*, int*>::value, ""); | ||
| static_assert(std::is_similar<int[], int[]>::value, ""); | ||
| static_assert(std::is_similar<int[9], int[]>::value, ""); | ||
| static_assert(std::is_similar<int[], int[9]>::value, ""); | ||
| static_assert(std::is_similar<int[9], int[9]>::value, ""); | ||
|
|
||
| static_assert(std::is_similar<const int, int>::value, ""); | ||
| static_assert(std::is_similar<int const*, int*>::value, ""); | ||
| static_assert(std::is_similar<int *const, int*>::value, ""); | ||
| static_assert(std::is_similar<int const[], int[]>::value, ""); | ||
| static_assert(std::is_similar<int const[9], int[]>::value, ""); | ||
| static_assert(std::is_similar<int const[], int[9]>::value, ""); | ||
| static_assert(std::is_similar<int const[9], int[9]>::value, ""); | ||
|
|
||
| static_assert(std::is_similar<int, const int>::value, ""); | ||
| static_assert(std::is_similar<int*, int const*>::value, ""); | ||
| static_assert(std::is_similar<int*, int *const>::value, ""); | ||
| static_assert(std::is_similar<int[], int const[]>::value, ""); | ||
| static_assert(std::is_similar<int[9], int const[]>::value, ""); | ||
| static_assert(std::is_similar<int[], int const[9]>::value, ""); | ||
| static_assert(std::is_similar<int[9], int const[9]>::value, ""); | ||
|
|
||
| static_assert(!std::is_similar<int&, int>::value, ""); | ||
| static_assert(!std::is_similar<int, int&>::value, ""); | ||
| static_assert(!std::is_similar<int&&, int>::value, ""); | ||
| static_assert(!std::is_similar<int, int&&>::value, ""); | ||
| static_assert(!std::is_similar<int&&, int&>::value, ""); | ||
| static_assert(!std::is_similar<int&, int&&>::value, ""); | ||
|
|
||
| static_assert(std::is_similar<int S::*, int S::*>::value, ""); | ||
| static_assert(std::is_similar<int& (S::*)(), int& (S::*)()>::value, ""); | ||
| static_assert(std::is_similar<int& (S::*)(int*), int& (S::*)(int*)>::value, ""); | ||
|
|
||
| static_assert(std::is_similar<int S::*, int S::*const>::value, ""); | ||
| static_assert(std::is_similar<int& (S::*)(), int& (S::*const)()>::value, ""); | ||
| static_assert(std::is_similar<int& (S::*)(int*), int& (S::*const)(int*)>::value, ""); | ||
|
|
||
| static_assert(!std::is_similar<int S::*, char S::*>::value, ""); | ||
| static_assert(!std::is_similar<int& (S::*)(), const int& (S::*)()>::value, ""); | ||
| static_assert(!std::is_similar<int& (S::*)(), int (S::*)()>::value, ""); | ||
| static_assert(!std::is_similar<int& (S::*)(), int (S::*)()>::value, ""); | ||
| static_assert(!std::is_similar<int (S::*)(char), int (S::*)(int)>::value, ""); | ||
| static_assert(!std::is_similar<int& (S::*)(int*), int& (S::*)(int const*)>::value, ""); | ||
| } | ||
|
|
||
| int main(int, char**) { | ||
| CheckIsSimilar(); | ||
| return 0; | ||
| } |