Boost logo

Boost Users :

Subject: [Boost-users] [type_erasure] Problem with iterators
From: Marco Guazzone (marco.guazzone_at_[hidden])
Date: 2015-01-24 02:56:54


Hi,

I'm new to the Type Erasure library.

I need to write a base class with type-erased forward iterators. To do
so I've taken inspiration from the print_sequence.cpp example I've
found in the Type Erasure source tree.
At the end of the email there is the whole code of my tentative,
called "erasure.cpp".

Unfortunately, I've problems (presumably) with const iterators which
cause the following compile error:

$ g++ -Wall -Wextra -pedantic -std=c++11 -I$HOME/sys/src/git/boost -o
erasure erasure.cpp -lm

*** [begin error] ***
In file included from
/home/sguazt/sys/src/git/boost/boost/type_erasure/iterator.hpp:20:0,
                 from erasure.cpp:2:
/home/sguazt/sys/src/git/boost/boost/type_erasure/operators.hpp: In
instantiation of ‘static R boost::type_erasure::dereferenceable<R,
T>::apply(const T&) [with R = double&; T =
__gnu_cxx::__normal_iterator<const double*, std::vector<double> >]’:
/home/sguazt/sys/src/git/boost/boost/type_erasure/detail/instantiate.hpp:91:9:
  required from ‘static void
boost::type_erasure::detail::instantiate_concept7::apply(Concept*,
Map*) [with Concept =
boost::mpl::vector<boost::type_erasure::forward_iterator<>,
boost::type_erasure::same_type<boost::type_erasure::deduced<boost::type_erasure::iterator_value_type<boost::type_erasure::_self>
>, double>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>; Map =
boost::mpl::map1<boost::mpl::pair<boost::type_erasure::_self,
__gnu_cxx::__normal_iterator<const double*, std::vector<double> > >
>]’
/home/sguazt/sys/src/git/boost/boost/type_erasure/any.hpp:225:13:
required from ‘boost::type_erasure::any<Concept, T>::any(U&&) [with U
= __gnu_cxx::__normal_iterator<const double*, std::vector<double> >&;
Concept = boost::mpl::vector<boost::type_erasure::forward_iterator<>,
boost::type_erasure::same_type<boost::type_erasure::deduced<boost::type_erasure::iterator_value_type<boost::type_erasure::_self>
>, double>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>; T =
boost::type_erasure::_self]’
erasure.cpp:36:40: required from ‘std::vector<_RealType>
base<T>::foo(IterT, IterT) [with IterT =
__gnu_cxx::__normal_iterator<const double*, std::vector<double> >; T =
double]’
erasure.cpp:77:73: required from here
/home/sguazt/sys/src/git/boost/boost/type_erasure/operators.hpp:134:44:
error: invalid initialization of reference of type ‘double&’ from
expression of type ‘const double’
     static R apply(const T& arg) { return *arg; }

*** [/end error] ***

The GCC version is 4.9.2.

Here below is the content of "erasure.cpp". If I comment lines below
the comment "THE FOLLOWING WON'T COMPILE" I get no error. So the
problem is due to the use of cbegin/cend.

*** [erasure.cpp] ***
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/iterator.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/same_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/smart_ptr.hpp>
#include <cmath>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>

namespace mpl = boost::mpl;
namespace te = boost::type_erasure;

template <typename T>
using fwd_iter_impl_t = te::any<
                            mpl::vector<
                                te::forward_iterator<>,

te::same_type<te::forward_iterator<>::value_type,T>>>;

template <typename T>
class base
{
protected:
    typedef fwd_iter_impl_t<T> fwd_iter_type;
public:
    virtual ~base() { }

    template <typename IterT>
    std::vector<T> foo(IterT first, IterT last)
    {
        return this->do_foo(first, last);
    }
private:
    virtual std::vector<T> do_foo(fwd_iter_type first, fwd_iter_type last) = 0;
}; // base

template <typename T>
class derived: public base<T>
{
private:
    typedef typename base<T>::fwd_iter_type fwd_iter_type;

    std::vector<T> do_foo(fwd_iter_type first, fwd_iter_type last)
    {
        const std::ptrdiff_t n = std::distance(first, last);
        std::vector<T> res(n);
        for (std::size_t i = 0; first != last; ++first, ++i)
        {
            res[i] = std::pow(*first,i)/n;
        }
        return res;
    }
}; // derived

int main()
{
    std::vector<double> dv;
    dv.push_back(5);
    dv.push_back(8);
    dv.push_back(11);

    boost::scoped_ptr< base<double> > p_base(new derived<double>());

    // begin/end
    const std::vector<double> foos = p_base->foo(dv.begin(), dv.end());
    for (std::size_t i = 0; i < foos.size(); ++i)
    {
        std::cout << "foos[" << i << "]: " << foos[i] << std::endl;
    }
//--- THE FOLLOWING WON'T COMPILE
    // cbegin/cend
    const std::vector<double> cfoos = p_base->foo(dv.cbegin(), dv.cend());
    for (std::size_t i = 0; i < cfoos.size(); ++i)
    {
        std::cout << "cfoos[" << i << "]: " << cfoos[i] << std::endl;
    }
}
*** [/erasure.cpp] ***

Thank you very much for your help.

Best,

-- Marco


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net