iterator adapter, little help please?

Previously, I had implemented a nice complex_to_real iterator adapter. It used the older real(z) and imag(z) that return value, not ref. Now it seems it gcc-4.0.1, at least, there are .imag() and .real() that return ref. So I thought I'd update c_to_r adaptor to use them. But, I can't seem to get this to work. Any hints? Here's what I get: g++ -c -I src test2.cc /usr/include/boost/iterator/iterator_facade.hpp: In static member function ‘static typename Facade::reference boost::iterator_core_access::dereference(const Facade&) [with Facade = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >]’: /usr/include/boost/iterator/iterator_facade.hpp:635: instantiated from ‘Reference boost::iterator_facade<I, V, TC, R, D>::operator*() const [with Derived = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >, Value = double, CategoryOrTraversal = boost::random_access_traversal_tag, Reference = double&, Difference = ptrdiff_t]’ /usr/lib/gcc/x86_64-redhat-linux/4.0.1/../../../../include/c++/4.0.1/bits/stl_algobase.h:285: instantiated from ‘static _OI std::__copy<_BoolType, std::random_access_iterator_tag>::copy(_II, _II, _OI) [with _II = double*, _OI = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >, bool _BoolType = false]’ /usr/lib/gcc/x86_64-redhat-linux/4.0.1/../../../../include/c++/4.0.1/bits/stl_algobase.h:317: instantiated from ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = double*, _OI = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >]’ /usr/lib/gcc/x86_64-redhat-linux/4.0.1/../../../../include/c++/4.0.1/bits/stl_algobase.h:335: instantiated from ‘static _OI std::__copy_normal<true, false>::copy_n(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, _OI = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >]’ /usr/lib/gcc/x86_64-redhat-linux/4.0.1/../../../../include/c++/4.0.1/bits/stl_algobase.h:387: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, _OutputIterator = boost::c_to_r_adapt<__gnu_cxx::__normal_iterator<main()::Complex*, std::vector<main()::Complex, std::allocator<main()::Complex> > > >]’ test2.cc:12: instantiated from here /usr/include/boost/iterator/iterator_facade.hpp:517: error: invalid initialization of reference of type ‘double&’ from expression of type ‘const double’

I see I can get this to work by adding an ugly const_cast. This seems to confirm my suspicion, that the problem is caused by iterator_facade having template <class Facade> static typename Facade::reference dereference(Facade const& f) { return f.dereference(); } IIUC the problem is the const in the above. To make my adaptor work, I did this: scalar_type & dereference() const { return (cnt % 2 == 0) ? const_cast<complex_type&>(*this->base_reference()).real() : const_cast<complex_type&>(*this->base_reference()).imag(); } So, basically, my dereference() has to lie about being const. Is this really correct? Is there another way to make my dereference without this ugly cast?

Neal Becker wrote:
I see I can get this to work by adding an ugly const_cast. This seems to confirm my suspicion, that the problem is caused by iterator_facade having template <class Facade> static typename Facade::reference dereference(Facade const& f) { return f.dereference(); }
Well the easy answer is this code is correct, it's your fault. Seriously dereferencing an iterator is a const operation it does not change the iterator state, even if the value the iterator points to can be changed this way. The state of the iterator is the position in the sequence it points to. If the iterator is const you can not change the position but still the object (if there is one) it points to. The mapping to pointer types in pseudocode iterator it; -> int* p; iterator const cit; -> int* const const_p; const_iterator it_to_const; -> int const* p_to_const; const_iterator const cit_to_const; -> int const* const const_p_to_const; The main difference being that the fact whether the iterator points to something const is molded into it's type while it's a qualifier in the formulation of the pointer type. Note that iterator/const_iterator is only a naming convention adopted by the standard. HTH Thomas
participants (2)
-
Neal Becker
-
Thomas Witt