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 шт):

Автор решения: Mikhailo

Просто вот так

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 
→ Ссылка