Re: Extending boost/tr1::array
On Apr 13, 12:48 pm, Stefan Chrobot <jan...@op.pl> wrote:
[]
Should the iterators be convertible - const to non-const and vice versa?
Should iterator and const_iterator be comparable? Should this code be
legal:
array<int, 2, 3>::iterator b = arr1.begin();
array<int, 2, 3>::const_iterator cb = arr1.begin();
b == cb;
b != cb;
b < cb;
b > cb;
b <= cb;
b >= cb;
cb == b;
cb != b;
cb < b;
cb > b;
cb <= b;
cb >= b;
I believe it should be legal, otherwise one could not iterate through a
non-const object with const iterator:
array<int, 2, 3> arr = ...;
typedef array<int, 2, 3>::const_iterator rit;
for(rit it = arr.begin(); it != arr.end(); ++it)
cout << *it << " ";
If it should be OK, then what is the best practice to implement it?
Template argument deduction does not consider conversions, so there is a
need to provide all combinations of operators for const_iterator and
iterator. The other way is to provide conversion from const_iterator to
iterator (xor vice versa) and put the operators as friends inside the
iterator class. But that would cause name injection and that's a bad
thing, isn't it?
One way to implement iterators is to provide two separate classes for
non-const and const versions. The const version would have a
conversion constructor from non-const one, so that non-const iterator
is implicitly convertable to const one. This is how they do it in GNU C
++ standard library.
Another way is to provide one class for both. The trick is to only
allow conversion non-const -> const, but not vice versa. Something
like that (using SFINAE):
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
template<class T>
struct iterator
{
iterator();
// conversion constructor to allow iterator<T> -> iterator<T
const> conversion
template<class U>
iterator(
iterator<U>
, typename boost::enable_if<boost::is_same<U const, T>,
int>::type = 0
);
};
int main()
{
iterator<int> i, j;
iterator<int const> k, l;
i = j; // okay, no conversion
i = k; // error, const -> non-const conversion
k = l; // okay, non-const -> const conversion
k = i; // okay, no conversion
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]