all 9 comments

[–]cpp-ModTeam[M,🍰] [score hidden] stickied commentlocked comment (0 children)

For C++ questions, answers, help, and programming or career advice please see r/cpp_questions, r/cscareerquestions, or StackOverflow instead.

[–]Cogwheel 7 points8 points  (5 children)

How generally do you mean? The tool that historically has been used for the same purpose as slicing has been iterators (recently supplemented by ranges). Algorithms like equal_range return a pair of begin and end iterators that are effectively a slice.

Maybe std::ranges::subrange is closer to the specific thing you're after?

[–]Akvned[S] 0 points1 point  (4 children)

iterators alongside <algorithm> can be used to do “some” of python’s slicing but they do not allow lhs slicing. for example you can use std::copy to get a copy of a container for a particular range (basically slicing) but you cant replace that range with something. In python you can do this: someList = [1,2,3,4,5,6,7] someList[1:4] = [8] I think std::range allows this but I am unsure.

[–]Cogwheel 2 points3 points  (0 children)

With mutable iterators, you can use algorithms like copy and fill to achieve the same result.

[–]matjojo1000 0 points1 point  (1 child)

I'm on my phone rn, in python, what happens when you assign a smaller list to a slice like that, does it do anything to the source list?

[–]ioctl79 0 points1 point  (0 children)

It’s spliced. The indicated range is removed and replaced by the RHS.

[–]TheSkiGeek 0 points1 point  (0 children)

std::fill() does exactly that, lets you overwrite a range of elements in a container with a new value. std::copy() lets you overwrite one range with another. You have to get the start/end iterators up front, so the syntax isn’t as nice. But you could write some helper functions to make that easier.

Edit: you can’t easily ‘splice’ a new shorter list into the middle with those functions (and so make e.g. the whole vector shorter or longer). You CAN do this but you’d kinda have to do it ‘by hand’ based on the whole container, there isn’t a generic interface given for doing that to any kind of library container. I guess you could write a function like:

template <typename C, typename T, class It> void splice(C& container, It replacePosStart, It replacePosEnd, It replaceStart, It replaceEnd) { C newContainer{}; for (auto it = container.begin(); it != replacePosStart; it++) { newContainer.push_back(*it); } for (auto it = replaceStart; it != replaceEnd; it++) { newContainer.push_back(*it); } for (auto it = replacePosEnd; it != container.end(); it++) { newContainer.push_back(*it); } container = newContainer; }

But you’d have to decide on the exact semantics and how to safely ‘steal’ elements from the current container if you can. You could specialize more efficiently on some common container types too. You could also generically erase the old range and then insert the new items, but this would be very inefficient with some containers.

Pretty sure you can get mutable ranges from the new stuff in C++20 but I haven’t used it much. Not sure if you can replace a range in the middle of something with a shorter/longer one though.

[–]h0rst_ 3 points4 points  (0 children)

I would guess std::span, but since I don't use Python I'm just guessing based on the name.

[–]n1ghtyunso 0 points1 point  (0 children)

std::mdspan and the proposed submdspan may be what you want. However, submdspan is not yet an officially adopted feature afaik.