[英]is any difference between std::forward<T> and std::forward<decltype(t)>?
are these functions equivalent? 这些功能相同吗?
template <class T>
void foo(T && t)
{
bar(std::forward<T>(t));
}
template <class T>
void foo2(T && t)
{
bar(std::forward<decltype(t)>(t));
}
template <class T>
void foo3(T && t)
{
bar(std::forward(t));
}
if they are, can I always use this macro for perfect forwarding? 如果是,我可以一直使用这个宏来完美转发吗?
#define MY_FORWARD(var) std::forward<decltype(var)>(var)
or just use 或者只是使用
bar(std::forward(t));
I believe foo2
and foo3
are same, but I found people are always use forward like foo
, is any reason to explicitly write the type? 我相信
foo2
和foo3
是一样的,但我发现人们总是像foo
一样使用前进,是否有任何理由明确写出类型?
I understand that T
and T&&
are two different types, but I think std::forward<T>
and std::forward<T&&>
always give the same result? 我知道
T
和T&&
是两种不同的类型,但我认为std::forward<T>
和std::forward<T&&>
总是给出相同的结果?
Edit: 编辑:
the reason I want to use macro is I want to save some typing on following C++1y code, I have many similar code in different places 我想使用宏的原因是我想在以下C ++ 1y代码上保存一些打字,我在不同的地方有很多类似的代码
#define XLC_FORWARD_CAPTURE(var) var(std::forward<decltype(var)>(var))
#define XLC_MOVE_CAPTURE(var) var(std::move(var))
template <class T, class U>
auto foo(T && func, U && para )
{
auto val = // some calculation
return [XLC_FORWARD_CAPTURE(func),
XLC_FORWARD_CAPTURE(para),
XLC_MOVE_CAPTURE(val)](){
// some code use val
func(std::forward<U>(para));
};
}
Are these functions two equivalent?
这些功能是两个相同的吗?
Yes , they are equivalent. 是的 ,它们是等价的。
decltype(t)
is the same as T&&
, and when used with std::forward
, there is no difference between T
and T&&
, regardless what T
is. decltype(t)
与T&&
相同,当与std::forward
, T
和T&&
之间没有区别,无论T
是什么。
Can I always use this macro for perfect forwarding?
我可以一直使用此宏来完美转发吗?
Yes, you can. 是的你可以。 If you want to make your code unreadable and unmaintainable, then do so.
如果您想使代码不可读且不可维护,那么请执行此操作。 But I strongly advise against it.
但我强烈建议不要这样做。 On the one hand, you gain basically nothing from using this macro.
一方面,你使用这个宏基本上没什么收获。 And on the other hand, other developers have to take a look at the definition to understand it, and it can result in subtle errors.
而另一方面,其他开发人员必须查看定义才能理解它,并且可能导致细微的错误。 For example adding additional parentheses won't work:
例如,添加额外的括号将无效:
MY_FORWARD((t))
In contrast, the form with decltype
is perfectly valid. 相反,具有
decltype
的形式是完全有效的。 In particular, it is the preferred way of forwarding parameters from generic lambda expressions, because there are no explicit type parameters: 特别是,它是从通用lambda表达式转发参数的首选方法,因为没有显式类型参数:
[](auto&& t) { foobar(std::forward<decltype(t)>(t)); }
I ignored the 3rd variant with std::forward(t)
, because it isn't valid. 我用
std::forward(t)
忽略了第3个变种,因为它无效。
Update: Regarding your example: You can use call-by-value instead of call-by-reference for the function template foo
. 更新:关于您的示例:您可以使用call-by-value而不是函数模板
foo
的call-by-reference 。 Then you can use std::move
instead of std::forward
. 然后你可以使用
std::move
而不是std::forward
。 This adds two additional moves to the code, but no additional copy operations. 这为代码添加了两个额外的移动,但没有额外的复制操作。 On the other hand, the code becomes much cleaner:
另一方面,代码变得更清晰:
template <class T, class U>
auto foo(T func, U para)
{
auto val = // some calculation
return [func=std::move(func),para=std::move(para),val=std::move(val)] {
// some code use val
func(std::move(para));
};
}
The accepted answer does not solve the problem in title completely. 接受的答案并没有完全解决标题中的问题。
A macro argument preserves the type of the expression. 宏参数保留表达式的类型。 A forwarding parameter in a template does not.
模板中的转发参数不会。 This means
t
in foo2
(as a forwarding function parameter) has the type T&&
(because this is the forwarding template parameter), but it can be something different when the macro is in other contexts. 这意味着
foo2
t
(作为转发函数参数)具有类型T&&
(因为这是转发模板参数),但是当宏处于其他上下文中时它可能是不同的。 For example: 例如:
using T = int;
T a = 42;
T&& t(std::move(a));
foo(MY_FORWARD(t)); // Which foo is instantiated?
Note here t
is not an xvalue, but an lvalue . 注意这里
t
不是 t
值 , 而是左值 。 With std::forward<T>(t)
, which is equivalent to std::forward<int>(t)
, t
would be forwarded as an lvalue. 使用
std::forward<T>(t)
,它等同于std::forward<int>(t)
, t
将作为左值转发。 However, with MY_FORWARD(t)
, which is equivalent to std::forward<int&&>(t)
, t
would be forwarded as an xvalue. 但是,使用
MY_FORWARD(t)
,它相当于std::forward<int&&>(t)
, t
将作为xvalue转发。 This contextual-dependent difference is sometime desired when you have to deal with some declared variables with rvalue reference types (not forwarding paramter even they may look like similar in syntax). 当您必须使用rvalue引用类型处理一些声明的变量时,这种依赖于上下文的差异有时是需要的(即使它们在语法上看起来类似,也不会转发参数)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.