Нажатие и выталкивание первого элемента std::tuple
Я пишу функцию в C++ с переменным количеством аргументов (и разных типов) таким образом
template<typename ...Ts>
void myFunction(Ts ...args)
{
//create std::tuple to access and manipulate single elements of the pack
auto myTuple = std::make_tuple(args...);
//do stuff
return;
}
То, что я хотел бы сделать, но я не знаю, как это толкать и извлекать элементы из кортежа, в частности первый элемент... что-то вроде
//remove the first element of the tuple thereby decreasing its size by one
myTuple.pop_front()
//add addThis as the first element of the tuple thereby increasing its size by one
myTuple.push_front(addThis)
Это возможно?
5 ответов
Вы можете сделать что-то вроде
template <typename T, typename Tuple>
auto push_front(const T& t, const Tuple& tuple)
{
return std::tuple_cat(std::make_tuple(t), tuple);
}
template <typename Tuple, std::size_t ... Is>
auto pop_front_impl(const Tuple& tuple, std::index_sequence<Is...>)
{
return std::make_tuple(std::get<1 + Is>(tuple)...);
}
template <typename Tuple>
auto pop_front(const Tuple& tuple)
{
return pop_front_impl(tuple,
std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
}
Обратите внимание, что он действительно простой и не обрабатывает кортеж ссылок или кортежей с квалифицированным типом const, но этого может быть достаточно.
С общими лямбдами вы можете сделать довольно элегантно:
template<typename Tuple>
constexpr auto pop_front(Tuple tuple) {
static_assert(std::tuple_size<Tuple>::value > 0, "Cannot pop from an empty tuple");
return std::apply(
[](auto, auto... rest) { return std::make_tuple(rest...); },
tuple);
}
Длина и типы std::tuple
определяются во время компиляции. Нет выталкивания во время выполнения или толкания невозможно. Вы могли бы использовать std::vector
обеспечить модификации во время выполнения.
Тип данных для вашего вектора может быть std::variant
(C++17) или boost::variant
, Оба типа принимают список поддерживаемых типов во время компиляции и могут быть заполнены любым значением соответствующего типа.
В качестве альтернативы, вы можете использовать std::any
(также C++ 17) или boost::any
хранить любой тип, но с другой семантикой доступа.
typedef boost::variant<int, std::string, double> value;
std::vector<value> data;
data.push_back(value(42));
data.psuh_back(value(3.14));
Вы не можете "удлинить" кортеж, добавив элементы - это не то, что представляет кортеж. Точка кортежа - это связующее соединение между различными значениями, которые составляют его, такими как "имя", "фамилия", "телефон".
То, что вам нужно, гораздо проще сделать с помощью вектора - вы можете легко добавлять к нему элементы и удалять их - его размер можно произвольно изменять по мере необходимости.
Нету. Кортеж не является вектором или изменяемым контейнером. Как только кортеж объявлен, его содержимое является тем, чем оно является.
std::tuple<int, char>
не имеет возможности превратить себя в
std::tuple<int>
удалив его последний элемент. std::tuple<int, char>
это совершенно другой тип, чем std::tuple<int>
,