We already implemented this, but it's good to have a test. gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-ca107.C: New test. --- gcc/testsuite/g++.dg/cpp2a/concepts-ca107.C | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-ca107.C diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ca107.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ca107.C new file mode 100644 index 00000000000..e18280a04bc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ca107.C @@ -0,0 +1,33 @@ +// NB comments CA107/US117 +// { dg-do compile { target concepts } } + +template <unsigned N> constexpr bool Atomic = true; +template <unsigned N> concept C = Atomic<N>; +template <unsigned N> concept Add1 = C<N + 1>; +template <unsigned N> concept AddOne = C<N + 1>; +template <unsigned M> void f() + requires Add1<2 * M>; +template <unsigned M> int f() + requires AddOne<2 * M> && true; + +int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N> + // with mapping similar to N -> 2 * M + 1 + +template <unsigned N> struct WrapN; +template <unsigned N> using Add1Ty = WrapN<N + 1>; +template <unsigned N> using AddOneTy = WrapN<N + 1>; +template <unsigned M> void g(Add1Ty<2 * M> *); +template <unsigned M> void g(AddOneTy<2 * M> *); + +void h() { + g<0>(nullptr); // OK, there is only one g +} +template <unsigned N> void f2() + requires Add1<2 * N>; +template <unsigned N> int f2() + requires Add1<N * 2> && true; +void h2() { + f2<0>(); // { dg-error "ambiguous" } ill-formed, no diagnostic required: + // required determination of subsumption between atomic constraints that are + // functionally equivalent but not equivalent +} base-commit: 14c831f5ef614aabb6a8c85712fb166600e6cc05 -- 2.18.1