You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The compiler behaves differently depending on whether the same requires clause for a function template is written between the template parameters and the function signature or after the function signature. In the former case it performs short-circuit evaluation (and agrees with gcc) whereas in the latter case it doesn't, leading to infinite recursion in my case.
However, short-circuit doesn't misbehave in all cases, since I didn't manage to hit the issue in a simpler case I tested (see below my case), so it doesn't seem to be related only to short-circuit evaluation, but concept evaluation as well.
The issue involves a struct Thing with a constructor template with a single argument, constrained by std::copy_constructible<T>, that could possibly be a better match than the copy constructor (when T = Thing). I expected that changing the contraint to !std::is_same_v<T, Thing> && std::copy_constructible<T> would solve the issue, but that worked or not depending on the location in which I wrote the requires clause.
#include<concepts>
#include<type_traits>structThing
{
Thing() = default;
Thing(const Thing&) = default;
#ifdef REQUIRES_AFTER_TEMPLATE
// Works (expected)template <typename T>
requires (!std::is_same_v<T, Thing> && std::copy_constructible<T>)
Thing(const T& /*t*/)
#else// Does NOT work (UNEXPECTED)// Conjunction short-circuit does not// seem to happen correctly:// https://en.cppreference.com/w/cpp/language/constraints#Conjunctionstemplate <typename T>
Thing(const T& /*t*/)
requires (!std::is_same_v<T, Thing> && std::copy_constructible<T>)
#endif
{}
};
voidtest(int a)
{
auto thing = Thing(a);
// This one breaks, when checking if// `Thing` models `std::copy_constructible`, because// the compiler tries to check// if the possibly-copy-constructor is a valid// copy constructor, which leads to checking// its constraints, therefore checking `std::copy_constructible` again,// which leads to infinite recursion
[[maybe_unused]] auto thing_of_thing = Thing(thing);
}
This program is well-formed since !is_same_v<int, int> is false, which should inhibit substitution into do_not_check<T> when checking the constraints on the function template f.
The compiler behaves differently depending on whether the same requires clause for a function template is written between the template parameters and the function signature or after the function signature. In the former case it performs short-circuit evaluation (and agrees with gcc) whereas in the latter case it doesn't, leading to infinite recursion in my case.
However, short-circuit doesn't misbehave in all cases, since I didn't manage to hit the issue in a simpler case I tested (see below my case), so it doesn't seem to be related only to short-circuit evaluation, but concept evaluation as well.
The issue involves a struct
Thing
with a constructor template with a single argument, constrained bystd::copy_constructible<T>
, that could possibly be a better match than the copy constructor (whenT = Thing
). I expected that changing the contraint to!std::is_same_v<T, Thing> && std::copy_constructible<T>
would solve the issue, but that worked or not depending on the location in which I wrote therequires
clause.Possibly related to #44304
My case (reproduction): Compiler Explorer
Simple case, no issues: Compiler Explorer
The text was updated successfully, but these errors were encountered: