英文:
std::forward's possible implementation
问题
以下是翻译好的内容:
- 为什么在第一种情况下编写
std::forward(x)
是可行的,但在第二种情况下不可行?也就是说,为什么在第二种情况下类型推断不起作用? - 编写
std::forward(x)
有什么问题?我明白它与标准的std::forward<T>(x)
签名不匹配,但随之而来的另一个问题是:为什么我们需要在这里明确指定类型?
英文:
I am curious why the below implementation is wrong?
template<typename T> // For lvalues (T is T&),
T&& std::forward(T&& param) // take/return lvalue refs.
{ // For rvalues (T is T),
return static_cast<T&&>(param); // take/return rvalue refs.
}
According to "Effective Modern C++" book, this is the possible implementation of std::forward
which is understandable.
template<typename T>
T&& forward(remove_reference_t<T>& param)
{
return static_cast<T&&>(param);
}
A user in the comments here answered like this:
> In the first case, you could get away with std::forward(x), but in the
> second you must explicitly provide the template parameters, as they
> cannot be inferred.
Questions
- Why in the 1st case writing
std::forward(x)
is possible, but for
the 2nd case it is not? I.e., why in the 2nd case type deduction
won't work? - What is wrong with writing
std::forward(x)
? I understand that it doesn't match with
the standard'sstd::forward<T>(x)
signature, but then another questions comes: why we need to specify type explicitly here?
答案1
得分: 3
(1) 是一个身份函数,它原样返回参数,这使它无用。
(2) 仅接受左值,并根据 T
返回左值或右值。请注意,std::forward
还有一个第二个重载,接受右值并返回右值,但它大多数情况下无用。
即,为什么在第二种情况下类型推断不起作用?
因为推断无法通过 typedefs (remove_reference_t
) 传播。而且,当原始值可以是 T
、T &
或 T &&
时,你怎么能取消 remove_reference
呢?
使用
std::forward(x)
有什么问题?
转发的整个目的是接受一个左值,并有条件地将其转换为右值或保持为左值。这需要外部信息来决定是否进行转换,在这种情况下,信息来自于 T
。
理论上,你可以获得你想要的语法(不需要模板参数),但这需要一个宏,例如只是 #define FWD(...) decltype(__VA_ARGS__)(__VA_ARGS__)
。
在这种情况下,额外的信息来自于 decltype(x)
,它具有检测变量的右值引用特性的神奇能力,即使变量名称本身始终是左值。
英文:
(1) is an identity function, it returns the argument as is, which makes it useless.
(2) only accepts lvalues, and returns either an lvalue or an rvalue depending on T
. Note that std::forward
also has a second overload that accepts an rvalue and returns an rvalue, but it's mostly useless.
> I.e., why in the 2nd case type deduction won't work?
Because deduction can't propagate through typedefs (remove_reference_t
). And indeed, how could you unremove_reference
, when the original could've been T
, T &
, or T &&
.
> What is wrong with writing std::forward(x)
?
The whole point of forwarding is to take an lvalue, and to conditionally either cast it to an rvalue or keep as an lvalue. This requires external information to decide whether to cast, and in this case it comes from T
.
In theory it's possible to get the syntax you want (without the template argument), but this requires a macro, e.g. just #define FWD(...) decltype(__VA_ARGS__)(__VA_ARGS__)
.
In this case the extra information comes from decltype(x)
, which has the magical ability to detect the rvalue-reference-ness of the variable, even though the variable name by itself is always an lvalue.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论