In the following program, the copy constructor of struct S is declared with the constraint that the class is not copy constructible:
#include <concepts>
template <typename T>
struct S {
S() = default;
S(const S &) requires (!std::copy_constructible<S>) {}
};
S<int> u;
S<int> v(u); //copy construction
static_assert( !std::copy_constructible<S<int>> );
I expected that the program would fail with an error, something like "constraint satisfaction depends on itself". And indeed, MSVC fails it, but with a rather obscure error message:
<source>(6): error C7608: atomic constraint should be a constant expression
<source>(6): note: the template instantiation context (the oldest one first) is
<source>(6): note: while evaluating concept 'copy_constructible<S<int> >'
Z:/compilers/msvc/14.40.33807-14.40.33811.0/include\concepts(170): note: while evaluating concept 'move_constructible<S<int> >'
Z:/compilers/msvc/14.40.33807-14.40.33811.0/include\concepts(105): note: while evaluating concept 'constructible_from<S<int>,S<int> >'
<source>(6): error C2131: expression did not evaluate to a constant
<source>(6): note: failure was caused by a read of an uninitialized symbol
<source>(6): note: see usage of 'std::copy_constructible<S<int>>'
But, both GCC and Clang successfully build the program without any warnings.
Online demo: https://gcc.godbolt.org/z/vTYnEGGva
Which implementation is correct here?