CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
601 lines
19 KiB
C++
601 lines
19 KiB
C++
// RUN: %clang_cc1 -std=c++2c -verify %s
|
|
|
|
template <class T> concept A = (T(), true);
|
|
template <class T> concept C = A<T> && true; // #C
|
|
template <class T> concept D = A<T> && __is_same(T, int);
|
|
|
|
|
|
template <class T> requires (A<T>)
|
|
constexpr int f(T) { return 0; };
|
|
template <class... T> requires (C<T> && ...)
|
|
constexpr int f(T...) { return 1; };
|
|
|
|
static_assert(f(0) == 0);
|
|
static_assert(f(1) == 0);
|
|
|
|
|
|
template <class... T> requires (A<T> && ...)
|
|
constexpr int g(T...) { return 0; };
|
|
template <class... T> requires (C<T> && ...)
|
|
constexpr int g(T...) { return 1; };
|
|
|
|
static_assert(g(0) == 1);
|
|
static_assert(g() == 1);
|
|
static_assert(g(1, 2) == 1);
|
|
|
|
|
|
|
|
template <class... T> requires (A<T> && ...)
|
|
constexpr int h(T...) { return 0; }; // expected-note {{candidate}}
|
|
template <class... T> requires (C<T> || ...)
|
|
constexpr int h(T...) { return 1; }; // expected-note {{candidate}}
|
|
|
|
static_assert(h(0) == 1); // expected-error {{call to 'h' is ambiguous}}
|
|
|
|
template <class... T> requires (A<T> || ...)
|
|
constexpr int i(T...) { return 0; }; // expected-note {{candidate}}
|
|
template <class... T> requires (C<T> && ...)
|
|
constexpr int i(T...) { return 1; }; // expected-note {{candidate}}
|
|
|
|
static_assert(i(0) == 1); // expected-error {{call to 'i' is ambiguous}}
|
|
|
|
|
|
template <class... T> requires (A<T> || ... || true) constexpr int j(T...) { return 0; }; // #j1
|
|
template <class... T> requires (C<T> && ... && true) constexpr int j(T...) { return 1; }; // #j2
|
|
|
|
static_assert(j(0) == 1);
|
|
// expected-error@-1 {{call to 'j' is ambiguous}}
|
|
// expected-note@#j1 {{candidate function [with T = <int>]}}
|
|
// expected-note@#j2 {{candidate function [with T = <int>]}}
|
|
// expected-note@#j2 {{imilar constraint expressions not considered equivalent}}
|
|
// expected-note@#j1 {{similar constraint expression here}}
|
|
|
|
|
|
static_assert(j() == 1);
|
|
// expected-error@-1 {{call to 'j' is ambiguous}}
|
|
// expected-note@#j1 {{candidate function [with T = <>]}}
|
|
// expected-note@#j2 {{candidate function [with T = <>]}}
|
|
// expected-note@#j2 {{imilar constraint expressions not considered equivalent}}
|
|
// expected-note@#j1 {{similar constraint expression here}}
|
|
|
|
|
|
|
|
template <class... T> requires (A<T> || ...)
|
|
constexpr int k(T...) { return 0; }; // expected-note {{candidate template ignored: constraints not satisfied [with T = <>]}}
|
|
template <class... T> requires (C<T> || ...)
|
|
constexpr int k(T...) { return 1; }; // expected-note {{candidate template ignored: constraints not satisfied [with T = <>]}}
|
|
|
|
static_assert(k(0) == 1);
|
|
static_assert(k() == 0); // expected-error {{no matching function for call to 'k'}}
|
|
static_assert(k(1, 2) == 1);
|
|
|
|
|
|
consteval int terse(A auto...) {return 1;}
|
|
consteval int terse(D auto...) {return 2;}
|
|
|
|
static_assert(terse() == 2);
|
|
static_assert(terse(0, 0) == 2);
|
|
static_assert(terse(0L, 0) == 1);
|
|
|
|
template <A... T>
|
|
consteval int tpl_head(A auto...) {return 1;}
|
|
template <D... T>
|
|
consteval int tpl_head(D auto...) {return 2;}
|
|
|
|
static_assert(tpl_head() == 2);
|
|
static_assert(tpl_head(0, 0) == 2);
|
|
static_assert(tpl_head(0L, 0) == 1);
|
|
|
|
|
|
namespace equivalence {
|
|
|
|
template <typename... T>
|
|
struct S {
|
|
template <typename... U>
|
|
void f() requires (A<U> && ...);
|
|
template <typename... U>
|
|
void f() requires (C<U> && ...);
|
|
|
|
template <typename... U>
|
|
void g() requires (A<T> && ...);
|
|
template <typename... U>
|
|
void g() requires (C<T> && ...);
|
|
|
|
template <typename... U>
|
|
void h() requires (A<U> && ...); // expected-note {{candidate}}
|
|
template <typename... U>
|
|
void h() requires (C<T> && ...); // expected-note {{candidate}}
|
|
};
|
|
|
|
void test() {
|
|
S<int>{}.f<int>();
|
|
S<int>{}.g<int>();
|
|
S<int>{}.h<int>(); // expected-error {{call to member function 'h' is ambiguous}}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
namespace substitution {
|
|
struct S {
|
|
using type = int;
|
|
};
|
|
|
|
template <typename... T>
|
|
consteval int And1() requires (C<typename T::type> && ...) { // #and1
|
|
return 1;
|
|
}
|
|
|
|
template <typename T, typename... U>
|
|
consteval int And2() requires (C<typename U::type> && ... && C<typename T::type>) { // #and2
|
|
return 2;
|
|
}
|
|
|
|
template <typename T, typename... U>
|
|
consteval int And3() requires (C<typename T::type> && ... && C<typename U::type>) { // #and3
|
|
return 3;
|
|
}
|
|
|
|
template <typename... T>
|
|
consteval int Or1() requires (C<typename T::type> || ...) { // #or1
|
|
return 1;
|
|
}
|
|
|
|
template <typename T, typename... U>
|
|
consteval int Or2() requires (C<typename U::type> || ... || C<typename T::type>) { // #or2
|
|
return 2;
|
|
}
|
|
|
|
template <typename T, typename... U>
|
|
consteval int Or3() requires (C<typename T::type> || ... || C<typename U::type>) { // #or3
|
|
return 3;
|
|
}
|
|
|
|
static_assert(And1<>() == 1);
|
|
static_assert(And1<S>() == 1);
|
|
static_assert(And1<S, S>() == 1);
|
|
// FIXME: The diagnostics are not so great
|
|
static_assert(And1<int>() == 1); // expected-error {{no matching function for call to 'And1'}}
|
|
// expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = <int>]}}
|
|
// expected-note@#and1 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And1<S, int>() == 1); // expected-error {{no matching function for call to 'And1'}}
|
|
// expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = <S, int>]}}
|
|
// expected-note@#and1 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And1<int, S>() == 1); // expected-error {{no matching function for call to 'And1'}}
|
|
// expected-note@#and1 {{candidate template ignored: constraints not satisfied [with T = <int, S>]}}
|
|
// expected-note@#and1 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And2<S>() == 2);
|
|
static_assert(And2<S, S>() == 2);
|
|
static_assert(And2<int>() == 2); // expected-error {{no matching function for call to 'And2'}}
|
|
// expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}}
|
|
// expected-note@#and2 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
|
|
static_assert(And2<int, int>() == 2); // expected-error {{no matching function for call to 'And2'}}
|
|
// expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = S, U = <int>]}} \
|
|
// expected-note@#and2 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And2<S, int>() == 2); // expected-error {{no matching function for call to 'And2'}}
|
|
// expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = <S>]}}
|
|
// expected-note@#and2 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And2<int, S>() == 2); // expected-error {{no matching function for call to 'And2'}}
|
|
// expected-note@#and2 {{candidate template ignored: constraints not satisfied [with T = int, U = <int>]}}
|
|
// expected-note@#and2 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(And3<S>() == 3);
|
|
static_assert(And3<S, S>() == 3);
|
|
static_assert(And3<int>() == 3); // expected-error {{no matching function for call to 'And3'}}
|
|
// expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}}
|
|
// expected-note@#and3 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
|
|
static_assert(And3<int, int>() == 3); // expected-error {{no matching function for call to 'And3'}}
|
|
// expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = <int>]}}
|
|
// expected-note@#and3 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
|
|
static_assert(And3<S, int>() == 3); // expected-error {{no matching function for call to 'And3'}}
|
|
// expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = S, U = <int>]}}
|
|
// expected-note@#and3 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
|
|
static_assert(And3<int, S>() == 3); // expected-error {{no matching function for call to 'And3'}}
|
|
// expected-note@#and3 {{candidate template ignored: constraints not satisfied [with T = int, U = <S>]}}
|
|
// expected-note@#and3 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
|
|
static_assert(Or1<>() == 1); // expected-error {{no matching function for call to 'Or1'}}
|
|
// expected-note@#or1 {{candidate template ignored: constraints not satisfied}}
|
|
static_assert(Or1<S>() == 1);
|
|
static_assert(Or1<int, S>() == 1);
|
|
static_assert(Or1<S, int>() == 1);
|
|
static_assert(Or1<S, S>() == 1);
|
|
static_assert(Or1<int>() == 1); // expected-error {{no matching function for call to 'Or1'}}
|
|
// expected-note@#or1 {{candidate template ignored: constraints not satisfied}}
|
|
// expected-note@#or1 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
|
|
static_assert(Or2<S>() == 2);
|
|
static_assert(Or2<int, S>() == 2);
|
|
static_assert(Or2<S, int>() == 2);
|
|
static_assert(Or2<S, S>() == 2);
|
|
static_assert(Or2<int>() == 2); // expected-error {{no matching function for call to 'Or2'}}
|
|
// expected-note@#or2 {{candidate template ignored: constraints not satisfied [with T = int, U = <>]}}
|
|
// expected-note@#or2 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
static_assert(Or3<S>() == 3);
|
|
static_assert(Or3<int, S>() == 3);
|
|
static_assert(Or3<S, int>() == 3);
|
|
static_assert(Or3<S, S>() == 3);
|
|
static_assert(Or3<int>() == 3); // expected-error {{no matching function for call to 'Or3'}}
|
|
// expected-note@#or3 {{candidate template ignored: constraints not satisfied}}
|
|
// expected-note@#or3 {{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
|
|
}
|
|
|
|
namespace bool_conversion_break {
|
|
|
|
template <typename ...V> struct A;
|
|
struct Thingy {
|
|
static constexpr int compare(const Thingy&) {return 1;}
|
|
};
|
|
template <typename ...T, typename ...U>
|
|
void f(A<T ...> *, A<U ...> *) // expected-note {{candidate template ignored: constraints not satisfied}}
|
|
requires (T::compare(U{}) && ...); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
|
|
|
|
void g() {
|
|
A<Thingy, Thingy> *ap;
|
|
f(ap, ap); // expected-error{{no matching function for call to 'f'}} \
|
|
// expected-note {{while checking constraint satisfaction}} \
|
|
// expected-note {{while substituting deduced template arguments}}
|
|
}
|
|
|
|
}
|
|
|
|
namespace nested {
|
|
|
|
template <typename... T>
|
|
struct S {
|
|
template <typename... U>
|
|
consteval static int f()
|
|
requires ((A<T> && ...) && ... && A<U> ) {
|
|
return 1;
|
|
}
|
|
|
|
template <typename... U>
|
|
consteval static int f()
|
|
requires ((C<T> && ...) && ... && C<U> ) {
|
|
return 2;
|
|
}
|
|
|
|
template <typename... U>
|
|
consteval static int g() // #nested-ambiguous-g1
|
|
requires ((A<T> && ...) && ... && A<U> ) {
|
|
return 1;
|
|
}
|
|
|
|
template <typename... U>
|
|
consteval static int g() // #nested-ambiguous-g2
|
|
requires ((C<U> && ...) && ... && C<T> ) {
|
|
return 2;
|
|
}
|
|
};
|
|
|
|
static_assert(S<int>::f<int>() == 2);
|
|
|
|
static_assert(S<int>::g<int>() == 2);
|
|
|
|
|
|
}
|
|
|
|
namespace GH99430 {
|
|
|
|
template <class _Ty1, class _Ty2>
|
|
using _Synth_three_way_result = int;
|
|
|
|
template <class... _Types>
|
|
class tuple;
|
|
|
|
template <int _Index>
|
|
struct tuple_element;
|
|
|
|
template <class, int...>
|
|
struct _Three_way_comparison_result_with_tuple_like {
|
|
using type = int;
|
|
};
|
|
|
|
template <class... _TTypes, int... _Indices>
|
|
requires(requires {
|
|
typename _Synth_three_way_result<_TTypes, tuple_element<_Indices>>;
|
|
} && ...)
|
|
|
|
struct _Three_way_comparison_result_with_tuple_like<tuple<_TTypes...>, _Indices...>{
|
|
using type = long;
|
|
};
|
|
|
|
static_assert(__is_same_as(_Three_way_comparison_result_with_tuple_like<tuple<int>, 0, 1>::type, int));
|
|
static_assert(__is_same_as(_Three_way_comparison_result_with_tuple_like<tuple<int>, 0>::type, long));
|
|
|
|
}
|
|
|
|
namespace GH88866 {
|
|
|
|
template <typename...Ts> struct index_by;
|
|
|
|
template <typename T, typename Indices>
|
|
concept InitFunc = true;
|
|
|
|
namespace ExpandsBoth {
|
|
|
|
template <typename Indices, InitFunc<Indices> auto... init>
|
|
struct LazyLitMatrix; // expected-note {{here}}
|
|
|
|
template <
|
|
typename...Indices,
|
|
InitFunc<index_by<Indices>> auto... init
|
|
>
|
|
struct LazyLitMatrix<index_by<Indices...>, init...> {
|
|
};
|
|
|
|
// FIXME: Explain why we didn't pick up the partial specialization - pack sizes don't match.
|
|
template struct LazyLitMatrix<index_by<int, char>, 42>;
|
|
// expected-error@-1 {{instantiation of undefined template}}
|
|
template struct LazyLitMatrix<index_by<int, char>, 42, 43>;
|
|
|
|
}
|
|
|
|
namespace ExpandsRespectively {
|
|
|
|
template <typename Indices, InitFunc<Indices> auto... init>
|
|
struct LazyLitMatrix;
|
|
|
|
template <
|
|
typename...Indices,
|
|
InitFunc<index_by<Indices...>> auto... init
|
|
>
|
|
struct LazyLitMatrix<index_by<Indices...>, init...> {
|
|
};
|
|
|
|
template struct LazyLitMatrix<index_by<int, char>, 42>;
|
|
template struct LazyLitMatrix<index_by<int, char>, 42, 43>;
|
|
|
|
}
|
|
|
|
namespace TypeParameter {
|
|
|
|
template <typename Indices, InitFunc<Indices>... init>
|
|
struct LazyLitMatrix; // expected-note {{here}}
|
|
|
|
template <
|
|
typename...Indices,
|
|
InitFunc<index_by<Indices>>... init
|
|
>
|
|
struct LazyLitMatrix<index_by<Indices...>, init...> {
|
|
};
|
|
|
|
// FIXME: Explain why we didn't pick up the partial specialization - pack sizes don't match.
|
|
template struct LazyLitMatrix<index_by<int, char>, float>;
|
|
// expected-error@-1 {{instantiation of undefined template}}
|
|
template struct LazyLitMatrix<index_by<int, char>, unsigned, float>;
|
|
|
|
}
|
|
|
|
namespace Invalid {
|
|
|
|
template <typename Indices, InitFunc<Indices>... init>
|
|
struct LazyLitMatrix;
|
|
|
|
template <
|
|
typename...Indices,
|
|
InitFunc<index_by<Indices>> init
|
|
// expected-error@-1 {{unexpanded parameter pack 'Indices'}}
|
|
>
|
|
struct LazyLitMatrix<index_by<Indices...>, init> {
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace GH135190 {
|
|
template <typename T>
|
|
concept A = __is_same_as(T, int) || __is_same_as(T, double) ;
|
|
|
|
template <typename T>
|
|
concept B = A<T> && __is_same_as(T, double);
|
|
|
|
template <class... Ts>
|
|
requires(A<Ts> && ...)
|
|
constexpr int g() {
|
|
return 1;
|
|
}
|
|
|
|
template <class... Ts>
|
|
requires(B<Ts> && ...)
|
|
constexpr int g() {
|
|
return 2;
|
|
}
|
|
|
|
static_assert(g<double>() == 2);
|
|
|
|
|
|
template <class... Ts>
|
|
concept all_A = (A<Ts> && ...);
|
|
|
|
template <class... Ts>
|
|
concept all_B = (B<Ts> && ...);
|
|
|
|
template <class... Ts>
|
|
requires all_A<Ts...>
|
|
constexpr int h() {
|
|
return 1;
|
|
}
|
|
|
|
template <class... Ts>
|
|
requires all_B<Ts...>
|
|
constexpr int h() {
|
|
return 2;
|
|
}
|
|
|
|
static_assert(h<double>() == 2);
|
|
}
|
|
|
|
|
|
namespace parameter_mapping_regressions {
|
|
|
|
namespace case1 {
|
|
namespace std {
|
|
template <class _Tp, class... _Args>
|
|
constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
|
|
template <class _Tp, class... _Args>
|
|
concept constructible_from = is_constructible_v<_Tp, _Args...>;
|
|
template <class _Tp>
|
|
concept default_initializable = true;
|
|
template <class> using iterator_t = int;
|
|
template <class _Tp>
|
|
concept view = constructible_from<_Tp, _Tp>;
|
|
template <class... _Views>
|
|
requires(view<_Views> && ...)
|
|
class zip_transform_view;
|
|
} // namespace std
|
|
struct IterDefaultCtrView {};
|
|
template <class... Views>
|
|
using Iter = std::iterator_t<std::zip_transform_view<Views...>>;
|
|
static_assert(
|
|
std::default_initializable<Iter<IterDefaultCtrView, IterDefaultCtrView>>);
|
|
|
|
}
|
|
|
|
namespace case2 {
|
|
|
|
template <class _Bp>
|
|
constexpr bool False = false;
|
|
|
|
template <class... _Views>
|
|
concept __zip_all_random_access = (False<_Views> && ...);
|
|
// expected-note@-1 {{evaluated to false}}
|
|
|
|
template <typename... _Views>
|
|
struct zip_view {
|
|
void f() requires __zip_all_random_access<_Views...>{};
|
|
// expected-note@-1 {{because 'int' does not satisfy}}
|
|
};
|
|
|
|
zip_view<int> test_v;
|
|
static_assert(!__zip_all_random_access<int>);
|
|
|
|
void test() {
|
|
test_v.f(); // expected-error {{invalid reference to function 'f'}}
|
|
}
|
|
|
|
}
|
|
|
|
namespace GH177245 {
|
|
|
|
template <class _Fun, class... _As>
|
|
concept __callable = requires (_Fun __fun, _As...) { __fun(); };
|
|
|
|
template <class... _Args>
|
|
struct __mdispatch {
|
|
template <class... _Ts>
|
|
requires (__callable<_Args, _Ts...> && ...)
|
|
void operator()();
|
|
};
|
|
|
|
static_assert(!__callable<__mdispatch<int>>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace GH190169 {
|
|
|
|
namespace _1 {
|
|
|
|
template <typename Type, typename... Choices>
|
|
concept OneOf = (... || __is_same(Type, Choices));
|
|
|
|
template <typename F, typename... Ts>
|
|
using check = decltype((F{}(Ts{}), ...));
|
|
|
|
using X = check<decltype([](auto val) {
|
|
[](OneOf<int, char> auto) {}(val);
|
|
}), char>;
|
|
|
|
}
|
|
|
|
namespace _2 {
|
|
|
|
template <typename T, typename U>
|
|
concept Same = __is_same(T, U);
|
|
|
|
template <typename Type, typename... Choices>
|
|
concept OneOf = (... || Same<Type, Choices>);
|
|
|
|
template <class... Ts>
|
|
struct visitor : Ts... { using Ts::operator()...; };
|
|
|
|
struct A {};
|
|
struct B {};
|
|
struct C {};
|
|
|
|
template <typename F, typename T, typename = decltype(F{}(T{}))>
|
|
struct check {};
|
|
|
|
template <typename F, typename... Ts>
|
|
struct check_all : check<F, Ts>... {};
|
|
|
|
using F = decltype([](auto val) {
|
|
visitor{[](const A&) {},
|
|
[](const OneOf<B, C> auto&) {}}(val);
|
|
});
|
|
|
|
check_all<F, A, B, C> x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace GH188505 {
|
|
|
|
template <class _Tp, class _Up>
|
|
concept same_as = __is_same(_Tp, _Up) && __is_same(_Up, _Tp);
|
|
|
|
template <typename T, typename... Ts>
|
|
concept AnyOf = (same_as<T, Ts> || ...);
|
|
|
|
struct Constant
|
|
{
|
|
template <typename T>
|
|
using alias = const T;
|
|
};
|
|
|
|
struct Mutable
|
|
{
|
|
template <typename T>
|
|
using alias = __remove_cv(T);
|
|
};
|
|
|
|
template <template <typename> typename M, typename T>
|
|
concept MutabilityAliasFor = requires {
|
|
requires AnyOf<M<T>, const T, __remove_cv(T)>;
|
|
requires same_as<M<M<T>>, M<T>>;
|
|
};
|
|
|
|
template <template <typename> typename M, typename... Ts>
|
|
concept MutabilityAliasForAllOf = (MutabilityAliasFor<M, Ts> && ...);
|
|
|
|
template <template <typename T> typename M>
|
|
concept MutabilityAlias = MutabilityAliasForAllOf<M, int, char, double>;
|
|
|
|
static_assert(AnyOf<char, const char, char>);
|
|
|
|
static_assert(MutabilityAliasFor<Constant::alias, int>);
|
|
static_assert(MutabilityAliasForAllOf<Constant::alias, char, int>);
|
|
|
|
static_assert(MutabilityAlias<Constant::alias>);
|
|
static_assert(MutabilityAlias<Mutable::alias>);
|
|
|
|
}
|