6

The documentation (and the implementation) of Boost.Range shows overloads of the mutating algorithms that take const refs as arguments. For instance Boost.Range's Sort documentation shows:

template<class RandomAccessRange>
RandomAccessRange& sort(RandomAccessRange& rng);

template<class RandomAccessRange>
const RandomAccessRange& sort(const RandomAccessRange& rng);

template<class RandomAccessRange, class BinaryPredicate>
RandomAccessRange& sort(RandomAccessRange& rng, BinaryPredicate pred);

template<class RandomAccessRange, class BinaryPredicate>
const RandomAccessRange& sort(const RandomAccessRange& rng, BinaryPredicate pred);

What is the point of overloads 2 and 4? Sure it's nice to be able to pass temporaries, but then const& makes this point kinda of moot. Rvalue-references would be most welcome, but it is my understanding that their support in Boost.Range is too invasive, and is "deferred" to the adoption of Range.V3 (it would be nice if meanwhile it were part of Boost).

akim
  • 8,255
  • 3
  • 44
  • 60
  • Looking at the source it looks like it is for containers that are `const` in the sense that the state of the container cannot be modified but the underlying elements can be mutated, – NathanOliver May 30 '17 at 14:31
  • 3
    `const iterator_pair` is a const range, but that doesn't mean the destination elements can't be sorted... – ildjarn May 30 '17 at 14:38

1 Answers1

6
template<class T>
struct span_t {
  T* b =0;
  T* e =0;
  T* begin() const { return b; }
  T* end() const { return e; }
  std::size_t size() const { return end()-begin(); }
  bool empty() const { return size()==0; }
  T& operator[](std::size_t i) const { return b[i]; }
  span_t()=default;
  span_t(span_t const&)=default;
  span_t& operator=(span_t const&)=default;
  span_t( T* s, T* f ):b(s),e(f) {}
  span_t( T* s, std::size_t l):span_t(s, s+l) {}
};

This is a (practical and useful) random access range.

All of its methods (except operator=) are const. You can sort it.

Not all ranges propogate const from the range to the elements in the range.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Thanks for the concrete example. But then: does it really make sense to have such a container? What does one gain from declaring it `const` then? – akim May 30 '17 at 15:22
  • 4
    @akim That isn't a container; it is a range view. `span` is riduculously useful. Much like when working with raw C arrays or buffers pointers are useful, `span` upgrades that for modern C++. It allows you to pass ranges in a buffer without having to copy a buffer or caring how exactly the buffer is allocated. It gives you bare-metal performance with lots of syntactic sugar. It is `const` because its value is only the span of the range in question, not the contents of the range, like how a const pointer and a pointer to const are distinct. Copy of a span does not copy elements, like a pointer. – Yakk - Adam Nevraumont May 30 '17 at 16:59