I have simple data structure called array
(similar to std::array). array
class have method called all()
. Here are method declarations:
const range<const_type_pointer> all() const;
range<type_point> all();
range
is class template, which is constructed by two iterators. Here is simplified version of range
class declaration:
template <typename Iterator>
class range {
typedef typename iterator_traits<Iterator>::type_value type_value;
typedef typename iterator_traits<Iterator>::type_reference type_reference;
typedef typename iterator_traits<Iterator>::type_pointer;
range(Iterator begin, Iterator end);
// methods & algorithms
// data members
mutable Iterator _begin;
mutable Iterator _end;
};
So basically, if I call method all on const array
object, it should call const
overload of method and return const range
. Now, in my algorithms section, I have simple algorithm with following signature:
template <typename UnaryFunction>
range forEach(UnaryFunction function);
Then I tried following test:
void test1(const array<int, 10>& array)
{
auto r = array.all();
r.forEach([](int i) { std::cout << i << " "; });
}
And second one:
void test2(const array<int, 10>& array)
{
auto r = array.all();
r.forEach([](int& i) { ++i; });
}
In first case, where I was just printing variable i
, compiler did not complained, even though I called non-const range
method on const range
object. In second case, compiler complained. Is this behaviour standard confornant?
As a compiler, I am using MSVS compiler.
First. Sice you are returning by value, it doesn't really make any difference if you are returning const range
or range
.
Second. auto r = array.all();
creates a copy of whatever was returned by all
. Your r is a non-const object, and non-const forEach
is used. But since the iterator is const in the second version, you can't modify the iterable.