C++ std::list аналог C# List.GetRange
Есть ли у std::list в C++ какой-то аналог List.GetRange из C#? Например, для списка
std::list<int> mylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
нужно сделать новый std::list без изменения mylist
std::list<int> mylist2 = GetRange(mylist, 3, 7);
mylist2 после этого должен получиться таким: { 4, 5, 6, 7, 8 }
Ответы (2 шт):
Просто вот так
int main() {
std::list<int> mylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::list<int> mylist2 { next(mylist.begin(), 3), next(mylist.begin(), 7) };
for (auto i : mylist2) cout << i << " ";
}
только надо помнить, что второй итератор указывает на элемент, который уже не входит в новый список.
Или так:
std::list<int> mylist2;
mylist2.assign(next(mylist.begin(), 3), next(mylist.begin(), 7));
А можно и функцию написать, как у вас:
std::list<int> GetRange(const std::list<int>& mylist, int b, int e) {
return std::list<int>(std::next(mylist.begin(), b),
std::next(mylist.begin(), e));
}
int main() {
std::list<int> mylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::list<int> mylist2 = GetRange(mylist, 3, 7);
for (auto i : mylist2) std::cout << i << " ";
}
Согласно описанию функции List.GetRange из неё должен возвращаться невладеющий список (поверхностная копия), это значит, что в терминологии C++ результирующий список будет содержать указатели или ссылки на исходные объекты. Таким образом, чтобы модификация через результат List.GetRange приводила к модификации исходных объектов. При этом из вашего вопроса следует, что нужен новый список std::list<int>, который согласно идеологии C++ является владеющим, т.е. модификация элементов через него уже не отразится на исходном списке. Т.о. если нужно именно сделать копии объектов просто вызывайте подходящий конструктор std::list (5). Это решение уже предложено в другом ответе.
Для решения с невладеющим списком нужно создавать подходящие обёртки в виде набора функций или отдельный шаблонный класс. В качестве примера, основная функция:
#include <iostream>
#include <algorithm>
#include <list>
std::list<int*> GetRange(std::list<int>* list, int index, int count) {
std::list<int*> r;
auto begin = std::next(list->begin(), index);
auto end = std::next(begin, count);
std::transform(begin, end, std::back_inserter(r), [](auto& e) { return &e; });
return r;
}
int main() {
std::list<int> l = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (auto& e: l) {
std::cout << e << " ";
}
std::cout << "\n";
auto nl = GetRange(&l, 3, 7);
std::cout << nl.size() << "\n";
**nl.begin() = 42;
for (auto& e: nl) {
std::cout << *e << " ";
}
std::cout << "\n";
for (auto& e: l) {
std::cout << e << " ";
}
std::cout << "\n";
}
1 2 3 4 5 6 7 8 9 10
7
42 5 6 7 8 9 10
1 2 3 42 5 6 7 8 9 10