[英]c++ decltype(auto) or decltype(std::forward<T>(value))?
[英]is any difference between std::forward<T> and std::forward<decltype(t)>?
这些功能相同吗?
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));
}
如果是,我可以一直使用这个宏来完美转发吗?
#define MY_FORWARD(var) std::forward<decltype(var)>(var)
或者只是使用
bar(std::forward(t));
我相信foo2
和foo3
是一样的,但我发现人们总是像foo
一样使用前进,是否有任何理由明确写出类型?
我知道T
和T&&
是两种不同的类型,但我认为std::forward<T>
和std::forward<T&&>
总是给出相同的结果?
编辑:
我想使用宏的原因是我想在以下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));
};
}
这些功能是两个相同的吗?
是的 ,它们是等价的。 decltype(t)
与T&&
相同,当与std::forward
, T
和T&&
之间没有区别,无论T
是什么。
我可以一直使用此宏来完美转发吗?
是的你可以。 如果您想使代码不可读且不可维护,那么请执行此操作。 但我强烈建议不要这样做。 一方面,你使用这个宏基本上没什么收获。 而另一方面,其他开发人员必须查看定义才能理解它,并且可能导致细微的错误。 例如,添加额外的括号将无效:
MY_FORWARD((t))
相反,具有decltype
的形式是完全有效的。 特别是,它是从通用lambda表达式转发参数的首选方法,因为没有显式类型参数:
[](auto&& t) { foobar(std::forward<decltype(t)>(t)); }
我用std::forward(t)
忽略了第3个变种,因为它无效。
更新:关于您的示例:您可以使用call-by-value而不是函数模板foo
的call-by-reference 。 然后你可以使用std::move
而不是std::forward
。 这为代码添加了两个额外的移动,但没有额外的复制操作。 另一方面,代码变得更清晰:
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));
};
}
接受的答案并没有完全解决标题中的问题。
宏参数保留表达式的类型。 模板中的转发参数不会。 这意味着foo2
t
(作为转发函数参数)具有类型T&&
(因为这是转发模板参数),但是当宏处于其他上下文中时它可能是不同的。 例如:
using T = int;
T a = 42;
T&& t(std::move(a));
foo(MY_FORWARD(t)); // Which foo is instantiated?
注意这里t
不是 t
值 , 而是左值 。 使用std::forward<T>(t)
,它等同于std::forward<int>(t)
, t
将作为左值转发。 但是,使用MY_FORWARD(t)
,它相当于std::forward<int&&>(t)
, t
将作为xvalue转发。 当您必须使用rvalue引用类型处理一些声明的变量时,这种依赖于上下文的差异有时是需要的(即使它们在语法上看起来类似,也不会转发参数)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.