Предположим, у меня есть некоторый шаблонный класс
template <typename T>
struct Dummy {
// ...
};
И я хочу перегрузить функцию ‘foo’ так, чтобы она принимала lvalue
или Rvalue ссылка на него. Я могу сделать это, используя некоторые IsDummy
черта характера
следующее:
template <typename A>
std::enable_if<IsDummy<A>::value, void>
foo(A &&dummy)
{
// ....
}
IIRC в каком-то проекте C ++ 11 было законно, что
template <typename A>
foo(Dummy<A> &&dummy)
{
// ....
}
будет принимать и lvalue- и value- ссылки.
Теперь мои вопросы:
а) Верно ли, что это было разрешено в каком-то проекте?
б) Почему была удалена эта функция / ошибка? Мне кажется, я где-то читал, что это произошло из-за конфликта с «понятиями».
Тем не менее, я не могу найти соответствующие ссылки для этого больше. У кого-то лучше память или закладки?
а) Верно ли, что это было разрешено в каком-то проекте?
Да, это было разрешено в том, что известно как «rvalue Reference 1.0» (см. N2118).
б) Почему была удалена эта функция / ошибка? Мне кажется, я где-то читал, что это произошло из-за конфликта с «понятиями».
Он был удален, потому что привязка ссылки на rvalue к lvalue может привести к нарушению «Принципа безопасной перегрузки типа» при наличии концепций:
Каждая функция должна быть изолированной по типу, независимо от того, как она была перегружена.
Например, если мы определим следующие перегрузки:
template< CopyConstructible T > void f( T const & t ); // #1
template< MoveConstructible T > void f( T && t ); // #2
Потом звоню f
с копируемым lvalue выберет # 1. Тем не менее, если T является не копируемым типом (например, std::unique_ptr
) тогда # 1 не является жизнеспособной перегрузкой, поэтому компилятор должен выбрать # 2, возможно, крадя ресурсы из lvalue без предупреждения.
Смотрите «rvalue reference 2.0» (N2844) Больше подробностей.
Имея информацию из ответа Эндрю, я также нашел очень читаемая статья на предмет (rvalue- / lvalue-ссылки), который также дает ссылки на то, как вещи развивались в этом вопросе.