Совет по std::forward
обычно ограничивается каноническим вариантом использования аргументов шаблона идеальной пересылки; некоторые комментаторы заходят так далеко, что говорят, что это единственное допустимое использование std::forward
. Но рассмотрите такой код:
// Temporarily holds a value of type T, which may be a reference or ordinary
// copyable/movable value.
template <typename T>
class ValueHolder {
public:
ValueHolder(T value)
: value_(std::forward<T>(value)) {
}
T Release() {
T result = std::forward<T>(value_);
delete this;
return result;
}
private:
~ValueHolder() {}
T value_;
};
В этом случае проблема идеальной пересылки не возникает: поскольку это шаблон шаблона, а не шаблон функции, клиентский код должен явно указывать T
и может выбрать, как и как его можно отфильтровать. Точно так же аргумент std::forward
не является "универсальной ссылкой".
Тем не менее, std::forward
выглядит здесь очень хорошо: мы не можем просто оставить его, потому что он не будет работать, если T
- тип только для перемещения, и мы не можем использовать std::move
потому что он не работает, если T
является ссылочным типом lvalue. Конечно, мы могли бы частично специализировать ValueHolder
использовать прямую инициализацию для ссылок и std::move
для значений, но это кажется чрезмерной сложностью, когда std::forward
выполняет задание. Это также кажется разумным концептуальным соответствием для значения std::forward
: мы пытаемся в целом перенаправить что-то, что может быть или не быть ссылкой, только мы перенаправляем его вызывающей функции, а не мы называем себя.
Это звуковое использование std::forward
? Есть ли причина избежать этого? Если да, то какая предпочтительная альтернатива?