Proper way of declaring `const` `boost::range`s

237 views Asked by At

When using boost::any_range, what's the correct way of specifying that the underlying container (if any) shouldn't be modified?

E.g., with the alias

template<typename T>
using Range = boost::any_range<T, boost::forward_traversal_tag>;

to declare a range that isn't capable of modifying the contents of the underlying container or "data source", should it be declared as

const Range<T> myRange;

or as

Range<const T> myRange;

?

I suspect the first version is the correct one. But is it guaranteed to keep the constness of the container, if, for example, I apply any of the boost::adaptors?


Edit

From the documentation, apparently the range_iterator metafunction "deduces" the constness of the underlying container by declaring the range with const T instead of T. That is, range_iterator::<const T>::type is const_iterator (if the underlying container has such member type), instead of iterator, so the container can't be modified through this iterator.

Does that mean that Range<const T> also uses const_iterators to traverse the range?

1

There are 1 answers

0
Anakhand On

Apparently the correct way to ensure that the values aren't modified is neither of those I mentioned.

From Boost.Range's documentation, we can see that any_range takes the following template parameters:

template<
    class Value
  , class Traversal
  , class Reference
  , class Difference
  , class Buffer = any_iterator_default_buffer
>
class any_range;

I strongly suspect the way to declare a "const range" is to specify const T as the Reference type template parameter, although, surprisingly, I still haven't been able to find any explicit indication in the documentation that this is so.

So a const range could be declared as:

template<class C>
using ConstRange = boost::any_range<C, boost::forward_traversal_tag, const C, std::ptrdiff_t>