Это:
#include <utility>
int main(){
const int ci = 2;
std::forward<int>(ci);
}
не работает, потому что вы не можете неявно отбрасывать const
. std::forward<T>(u)
следует читать как:
Вперед u
как T
.
Вы пытаетесь сказать:
Forward an lvalue `const int` as an rvalue `int`.
, который выбрасывает const
. Чтобы не выбросить const
, вы можете:
#include <utility>
int main(){
const int ci = 2;
std::forward<const int>(ci);
}
что говорит:
Forward an lvalue `const int` as an rvalue `const int`.
В вашем коде:
template<class T>
void foo(holder<T> const& h)
{
std::tuple<T> t; // contrived, actual function takes more parameters
std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}
квалификатор const
в h
влияет на выражение выбора элемента данных h.value
. h.value
является const
значением int
. Вы можете использовать forward
, чтобы изменить его на const
rvalue int
, или вы можете использовать forward
, чтобы передать его без изменений (как const
lvalue int
). Вы могли бы даже использовать forward
, чтобы добавить volatile
(хотя я не могу придумать вескую причину для этого).
В вашем примере я не вижу смысла вообще использовать forward
(если вы не снимаете const
с h
).
std::get<0>(t) = h.value; // h.value is `const T`
Ваш комментарий даже по-прежнему правильный.
Это сухое чтение, но N2951 показывает, что можно и что нельзя делать с forward
и почему. Это было изменено N3143 непосредственно перед стандартизацией, но варианты использования и обоснование по-прежнему действительны и неизменны в окончательной формулировке N3143.
Вещи, которые вы можете сделать с forward
:
- Вы можете переслать lvalue как lvalue.
- Вы можете переслать lvalue как значение.
- Вы можете переслать rvalue как rvalue.
- Вы можете переслать менее квалифицированные cv выражения в более квалифицированные cv выражения.
- Вы можете пересылать выражения производного типа в доступный однозначный базовый тип.
Вещи, которые вы можете не делать с forward
:
- Вы не можете переслать rvalue как lvalue.
- Вы не можете пересылать больше выражений с квалификацией cv в выражения с меньшим количеством cv.
- Вы не можете пересылать произвольные преобразования типов (например, пересылать
int
как double
).