Получить последний элемент пакета параметров в C ++ 17 / C ++ 20 - PullRequest
3 голосов
/ 20 апреля 2020

Я хотел бы получить последний элемент пакета параметров. Я сделал это с помощью следующего кода GodBolt :

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

Но теперь я получаю предупреждение

левый операнд оператора запятой не действует

Но это именно то, чего я хотел достичь ... Есть ли способ прояснить это. В общем, мне нравится получать предупреждения о неиспользуемых значениях, поэтому я не хочу отключать их все (-Wno-unused-value).

Кроме того, я могу сделать это с рекурсивным шаблоном, но сгибом выражение здесь, кажется, лучше.

Ответы [ 4 ]

5 голосов
/ 20 апреля 2020

Обтекание args при любом вызове функции приведет к удалению предупреждения.

Вы можете создать функцию идентификации специально для этой цели, но вы также можете использовать std::forward и получить надлежащую переадресацию в качестве бонуса.

template<typename... Args>
decltype(auto) last(Args&&... args){
   return (std::forward<Args>(args), ...);
}
1 голос
/ 20 апреля 2020

Создайте кортеж и получите последний элемент:

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)>>);
}

Демо

C ++ 11 Friendly Demo
0 голосов
/ 21 апреля 2020

Как предполагает HolyBlackCat, самый простой способ убрать это предупреждение - использовать «удостоверение / фиктивная функция», например так:

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

0 голосов
/ 20 апреля 2020

Вы можете использовать другую реализацию (она менее эффективна, но компилятор должен быть в состоянии устранить неэффективность здесь)

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)... ); }
...