MSVC /std:c++20 reports the error shown below for constrained auto&&
#include<concepts>
class Base { public: Base() {} };
class Derived : public Base { public: Derived() {} };
template<typename T> concept con = std::is_class_v<T>
&& std::derived_from<T, Base>;
void f(con auto&& x) {}
int main()
{
f(Derived()); // r value: Ok
Derived d;
f(d); // l-value: no matching overloaded function found
}
Remove "con" from "con auto&&" and the above code compiles with no error. I would like to understand why adding a constraint to an auto&& template parameter changes it from a "universal reference" to an R-value only reference. Does this behavior conform to the C++20 standard or is it something unique to MSVC?
Searched C++ forums on the internet and found nothing explaining this specific language use case. However there may be something that I missed or otherwise did not notice.
Because on the instantiation with Derived&
you'll be checking
std::derived_from<Derived&, Base>
// this guy ^
To make your concept immune to varying value categories, you can use std::decay_t
:
template<typename T>
concept con =
std::is_class_v<std::decay_t<T>> &&
std::derived_from<std::decay_t<T>, Base>;
so purely the types are checked w/o their value categories