This question already has an answer here:
-
Can we send part of vector as a function argument?
5 answers
I want to see if it is possible to pass part of vector to a function so that it appears as a normal vector to the function. More importantly, I want this to be done in O(1), constant time. I don't want to iterate the vector to make a new one. In fact, I also want the size of the new vector to change to 40 in the following example.
void func(vector <int> &v){
//calling index 10 to 50 of v
func(v[10..50])
}
Use iterators as the parameters to the range-based function, and pass in the required range. Your code in the function become
funcWithRange(v.cbegin()+10, v.cbegin()+50);
with function signature
void funcWithRange(std::vector<int>::const_iterator first, std::vector<int>::const_iterator last)
This could be generalized by making this a function template with the vector
member type as its template parameter, or still further to any container supporting this type of range iteration. As noted in the comments, <algorithm>
has many examples of this pattern.
std::distance(first, last);
will return the desired altered size. I don't think you can get closer to meeting your requirements without making a physical copy.
There is a means to achieve something similar to this that is being proposed for inclusion in the C++
standard. It is called a span
and it operates like a vector in some ways.
#include <gsl/span>
void func(gsl::span<int> sp)
{
for(auto& i: sp)
std::cout << i << '\n';
}
int main()
{
// ...
std::vector<int> v(100);
// put something in the vector (numbers 0 - 99)
std::iota(std::begin(v), std::end(v), 0);
// wrap the container in a span
auto sp = gsl::make_span(v);
// send parts of it to functions
func(sp.subspan(10, 50));
}
The span
presents a window onto the original vector so it is a reference type. It doesn't contain its own data just pointers to the data in the vector. As such they are lightweight and designed to be passed by value.
An implementation of span
can be found here: https://github.com/Microsoft/GSL
This is the recommended way of passing contiguous containers in the Best Practices guide by Bjarne Stroustrup and Herb Sutter.
The guidelines can be found here: CppCoreGuidelines.md
If you have a vector of say 100 elements
std::vector<int> v(100);
and you want to call void f(std::vector<int> v)
with the first 10 elements, simply call the function as
f({v.cbegin(), v.cbegin() + 10});
That will construct a new vector from the two iterators (by copying the elements) and pass the new vector to f
.