Considere o seguinte trecho de código.
template <typename T>
concept IsRValue = std::is_rvalue_reference_v<T>;
void funTakingRValues(IsRValue auto&& val)
{
std::cout << val << std::endl;
}
int main()
{
auto && x = 5;
std::cout << "Is rvalue reference = " << std::is_rvalue_reference_v<decltype(x)> << std::endl;
funTakingRValues(std::forward<decltype(x)>(x));
}
Neste caso, x
é considerada uma referência de valor r com base no resultado da instrução cout. Mas a restrição IsRValue que depende do mesmo tipo de traço não é satisfeita. O que está acontecendo?
Conforme declarado por HolyBlackCat ,
T
é deduzido como umint
desde queauto
seja qualificado por&&
. Para corrigir seu conceito, você pode adicionar a referência rvalue de volta paraT
comoe agora se
T
é umint
então ele se tornaint&&
e passa o traço. Se um lvalueint
é passado para a função entãoT
é deduzido paraint &
e adicionar uma referência rvalue a isso ainda resulta emint&
por causa das regras de colapso de referência e a função irá dar erro.Você pode ver isso funcionando neste exemplo ao vivo .
O conceito só recebe a
auto
parte sem&&
, entãoint
no seu caso.Observe que, como é uma referência de encaminhamento, passar um lvalue deduziria o
auto
paraT &
, e é isso que o conceito receberia.