Как распаковать только часть пакета параметров при объявлении переменной?

Я хочу создать кортеж, который игнорирует число N первых типов в пакете параметров, что-то вроде этого

template<typename... Args>
class Foo
{
 std::tuple</*Args<2>,Args<3>,Args<4> and so on*/> tup;
}

В настоящее время единственное решение, которое я нашел для достижения чего-то близкого к этому,

template<typename... Args>
    class Foo
    {
      std::vector<std::variant<std::monostate//work for empty parameter pack,Args...>> partargs;
    }

Но это усложнит мне жизнь в будущем, поэтому мне было интересно, есть ли лучшее решение?

Является ли количество пропущенных аргументов небольшим и фиксированным?

HolyBlackCat 09.04.2022 21:06

Количество аргументов, которое будет исправлено для этого конкретного шаблона (чтобы я мог иметь шаблон int), а количество пропущенных аргументов должно быть небольшим (максимум три)

Extroias 09.04.2022 21:15

template <typename, typename, typename ...Args> в порядке? Или вы хотите, чтобы constexpr int контролировал количество пропущенных аргументов?

HolyBlackCat 09.04.2022 21:17

Да, это было бы нормально

Extroias 09.04.2022 21:21
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
4
68
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Использование частичной специализации шаблона класса должно быть достаточным

#include <tuple>

template<std::size_t N, typename... Args>
struct ignore_first;

template<std::size_t N, typename First, typename... Args>
struct ignore_first<N, First, Args...> : ignore_first<N-1, Args...> { };

template<typename First, typename... Args>
struct ignore_first<0, First, Args...> {
  using type = std::tuple<First, Args...>;
};

template<std::size_t N>
struct ignore_first<N> {
  using type = std::tuple<>;
};

static_assert(std::is_same_v<
  ignore_first<0, int, long, char>::type, std::tuple<int, long, char>>);
static_assert(std::is_same_v<
  ignore_first<1, int, long, char>::type, std::tuple<long, char>>);
static_assert(std::is_same_v<
  ignore_first<2, int, long, char>::type, std::tuple<char>>);
static_assert(std::is_same_v<
  ignore_first<3, int, long, char>::type, std::tuple<>>);

Демо

Вариант ответа 康桓瑋, использующий std::conditional и свойство std::tuple_cat объединять кортежи, в том числе пустые, во избежание рекурсии.

#include <tuple>
#include <utility>
#include <type_traits>

template <std::size_t N, typename ... Args, std::size_t ... Is>
decltype( std::tuple_cat(
             std::declval<
                std::conditional_t<
                   (N <= Is),
                   std::tuple<Args>,
                   std::tuple<>>>()...) )
   foo (std::index_sequence<Is...>);


template <std::size_t N, typename ... Args>
using ignore_first
   = decltype(foo<N, Args...>(std::index_sequence_for<Args...>{}));

static_assert(std::is_same_v<
  ignore_first<0, int, long, char>, std::tuple<int, long, char>>);
static_assert(std::is_same_v<
  ignore_first<1, int, long, char>, std::tuple<long, char>>);
static_assert(std::is_same_v<
  ignore_first<2, int, long, char>, std::tuple<char>>);
static_assert(std::is_same_v<
  ignore_first<3, int, long, char>, std::tuple<>>);


int main()
{
}

Используя обычный трюк с последовательностью индексов, здесь со смещенными индексами и немедленно вызываемыми лямбда-выражениями, можно получить немного короче, чем в принятом ответе (и, возможно, также лучше с точки зрения времени компиляции, поскольку он нерекурсивный):

#include<tuple>
#include<type_traits>

template<size_t N, typename ... args_t>
constexpr auto skip_first(args_t&& ... args)
{
    return []<size_t ... I>
    (std::index_sequence<I ...>, auto tup)
    {
        return std::tuple{std::get<I+N>(std::move(tup)) ...};
    }(std::make_index_sequence<sizeof...(args)-N>{}, std::tuple{std::forward<args_t>(args)...});
}

int main()
{
    static_assert(skip_first<2>(1,2,3,4)==std::tuple{3,4});
}

Для этого требуется C++20. В С++ 17 вам нужно определить две отдельные функции:

template<size_t N, size_t ... I, typename tuple_t>
constexpr auto skip_first(std::index_sequence<I ...>, tuple_t tup)
{
    return std::tuple{std::get<I+N>(std::move(tup)) ...};
}

template<size_t N, typename ... args_t>
constexpr auto skip_first(args_t&& ... args)
{
    return skip_first<N>(std::make_index_sequence<sizeof...(args)-N>{}, std::tuple{std::forward<args_t>(args)...});
}

Хороший ответ, но я использую С++ 17

Extroias 10.04.2022 00:51

@Extroias: см. обновление к моему ответу.

davidhigh 10.04.2022 08:01

Другие вопросы по теме

Почему в реализации std::any используется указатель на функцию + коды операций функции вместо указателя на виртуальную таблицу + виртуальные вызовы?
Количество std:: необязательных типов в вариативном кортеже шаблона
Как создать интерфейс, позволяющий создавать различные вложенные производные классы в C++?
Убедитесь, что производный класс реализует статический метод, сохраняя перемещение/перемещение по умолчанию
Может ли Boost::asio::post прерывать работающий поток?
Gcc: недопустимая ошибка «использование удаленной функции» (конструктор копирования)?
С++ OpenSSL-хэш файла не является правильным
Как мне обратиться к классу с несколькими типами шаблонов только одним из типов?
Базовый частный конструктор CRTP и производный класс друзей вызывают ошибку компиляции с использованием С++ 17 и юниформ-инициализации
Вариативный шаблон, возвращающий N-кортеж на основе неизвестного количества аргументов