Ответ 1
Являются ли эти функции двумя эквивалентными?
Да, они эквивалентны. decltype(t)
совпадает с T&&
, а в случае std::forward
нет разницы между T
и T&&
, независимо от того, что T
.
Могу ли я использовать этот макрос для идеальной пересылки?
Да, вы можете. Если вы хотите сделать свой код нечитаемым и неподъемным, сделайте это. Но я категорически против этого. С одной стороны, вы ничего не получаете от использования этого макроса. И, с другой стороны, другие разработчики должны взглянуть на определение, чтобы понять его, и это создает потенциал для тонких ошибок. Например, добавление дополнительных круглых скобок не будет работать:
MY_FORWARD((t))
Напротив, форма с decltype
вполне допустима. В частности, это предпочтительный способ пересылки параметров из общих лямбда-выражений, поскольку нет явных параметров типа:
[](auto&& t) { foobar(std::forward<decltype(t)>(t)); }
Я проигнорировал третий вариант с std::forward(t)
, потому что он недействителен.
Обновление:. В отношении вашего примера: вместо call-by-reference для шаблона функции foo
вы можете использовать call-by-value. Затем вы можете использовать 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));
};
}