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.
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. In particular, it is the preferred way of forwarding parameters from generic lambda expressions, because there are no explicit type parameters:
[](auto&& t) { foobar(std::forward<decltype(t)>(t)); }
I ignored the 3rd variant with std::forward(t)
, because it isn't valid.
Update: Regarding your example: You can use call-by-value instead of call-by-reference for the function template foo
. Then you can use std::move
instead of 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));
};
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…