在 C++17 / C++20 中获取参数包的最后一个元素

Get Last element of parameter pack in C++17 / C++20

我想获取参数包的最后一个元素。我用下面的代码 GodBolt:

template<typename... Args>
auto last(Args&&... args){
   const auto& last = (args, ...);
   return last;
}

但现在我收到警告

left operand of comma operator has no effect

但这正是我想要实现的...有没有办法说清楚。 一般来说,我喜欢收到未使用值的警告,所以我不想禁用所有这些值 (-Wno-unused-value)。

此外,我可以使用递归模板来完成,但折叠表达式在这里似乎更好。

在任何函数调用中包装 args 将删除警告。

您可以专门为此目的制作一个身份功能,但您也可以使用 std::forward 并获得适当的转发作为奖励。

template<typename... Args>
decltype(auto) last(Args&&... args){
   return (std::forward<Args>(args), ...);
}

创建元组并获取最后一个元素:

template<typename... Args>
auto last(Args&&... args)
{
    return std::get<sizeof...(Args)-1>(std::forward_as_tuple(args...));
}

测试:

int main()
{
    auto&& last_element = last(1, 1.0, true);
    static_assert(std::is_same_v<bool, std::remove_cvref_t<decltype(last_element)>>);
}

Demo

C++11 Friendly Demo

您可以使用其他实现(它的效率较低,但编译器应该能够消除此处的低效率)

template <class T>
decltype(auto) last(T && ... t) { return t; }

template <class ... TT,class T>
decltype(auto) last(T &&,TT && ... tt) { return last( std::forward<TT>(tt)... ); }

正如 HolyBlackCat 所建议的那样,删除此警告的最简单方法是使用这样的 "identity / dummy-function":

template<typename T>
constexpr inline decltype(auto) identityFkt(T&& t)
{
    return std::forward<T>(t);
}

可以这样使用:

const auto& last = (identityFkt(std::forward<AParamPack>(aParamPack)), ...);

它产生相同的程序集(已检查 @godbolt)- 没有开销(使用 -O3)。

谢谢:@HolyBlackCat