7
\$\begingroup\$

I needed to pass a const reference to part of a std::vector without copy. I posted the previous version in my earlier question, thank you for the great support! As far as I know this version supports not only std::vectors but any kind of iterator based continuous containers!

Some research, particularly this SO question, suggested that it is not something supported by default(at least in pre-c++20 std), so I created my own code for it:

#include <iterator>
#include <vector>
template <typename Iterator = std::vector<double>::const_iterator>
class ConstVectorSubrange{
public:
 using T = typename Iterator::value_type;
 ConstVectorSubrange(Iterator start_, std::size_t size_)
 : start(start_)
 , range_size(size_)
 { }
 ConstVectorSubrange(Iterator begin_, Iterator end_)
 : start(begin_)
 , range_size(std::distance(start, end_))
 { }
 const T& operator[](std::size_t index) const{
 assert(index < range_size);
 return *std::next(start, index);
 }
 const T& front() const{
 return *begin();
 }
 const T& back() const{
 return *std::next(end(), -1);
 }
 std::size_t size() const{
 return range_size;
 }
 Iterator begin() const{
 return start;
 }
 Iterator end() const{
 return std::next(start, range_size);
 }
private:
 const Iterator start;
 const std::size_t range_size;
};

In C++20 the functionality is available in std::span, so I am trying to achieve this with c++17 latest. Target for my code is c++11, but c++17 features are also present in the project I am using this in. I'm not sure I would go up to c++20 as I'm still not sure how widespread it is yet, but I'm still open to it.

An example of using this would be a member function where not the whole array is visible, although copies are to be avoided:

#include <vector>
class BigData{
 std::vector<int> big_array = vector<int>(10000);
public:
 ConstVectorSubrange get_last_five_thousand_elements(){
 return{(big_array.end()-5000), big_array.end()};
 }
};

How can this code be improved? I tried to remove the dependent typename, but I could only do that with C++20 std::iter_reference_t. Is there no other way to deduce T explicitly?

asked Nov 27, 2021 at 11:55
\$\endgroup\$
0

1 Answer 1

5
\$\begingroup\$

With C++17 the compiler should be able to deduce the template type automatically by using the following:

template <typename Iterator>
class ConstVectorSubrange {
public:
 using T = typename Iterator::value_type;
 // ...
}
int main() 
{
 std::vector v{ 1, 2, 3, 4, 5, 6, 7, 8 };
 ConstVectorSubrange range(v.begin() + 2, v.end() - 2);
}

I'm not sure why you have included <iterator> and failed to include <cassert>?

Good:

I like that you can now use the foreach loop:

std::vector v{ 7, 7, 3, 4, 5, 6, 7, 7, 8, 9 };
ConstVectorSubrange vsr(v.begin() + 4, v.end());
for (int i : vsr)
 std::cout << i << "\n";

And all the cool stuff from <algorithm>

std::cout << std::count(vsr.begin(), vsr.end(), 7) << "\n";

Ideas:

It would be pretty cool if you could include a step or stride to have a slice of the vector. Something like this:

std::vector v{ 1, 2, 3, 4, 5, 6 };
std::size_t step = 2;
ConstVectorSubrange r(v.begin() + 1, v.end(), step);
for (int i : r)
 std::cout << i << "\n";
// expected results 2, 4, 6
answered Nov 27, 2021 at 14:18
\$\endgroup\$
3
  • 1
    \$\begingroup\$ <assert.h> is not a C++ header. You probably mean <cassert>. \$\endgroup\$ Commented Nov 27, 2021 at 19:26
  • \$\begingroup\$ Thank you very much! :) \$\endgroup\$ Commented Nov 28, 2021 at 13:56
  • 1
    \$\begingroup\$ @DavidTóth, cool! You got so close that I almost feel like I should have added a spoiler alert ;-) \$\endgroup\$ Commented Nov 28, 2021 at 14:06

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.