Boost logo

Boost Users :

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


On Sat, Jan 24, 2015 at 9:29 PM, Steven Watanabe <watanabesj_at_[hidden]> wrote:
> AMDG
>
> On 01/24/2015 12:56 AM, Marco Guazzone wrote:
>> 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:
>>
>
> Iterators are mutable by default. If you want
> a const iterator, you need to specify the reference
> type. (If you look at the range print example,
> it uses forward_iterator<_iter, const _t&>)
>

[big cut]

Hi Steven,

Probably I haven't correctly understand your suggestion since now that
I've commented the definition of "fwd_iter_impl_t" and replaced the
"typedef" definition in "base" class with the following one:

struct _t: te::precision { };
struct _iter: te::precision { };
//...
typedef te::any< mpl::vector< te::forward_iterator<_iter, const _t&>,
                              te::same_type<_t,
te::forward_iterator<_iter, const _t&>::value_type>>,
                 _iter> fwd_iter_type;

I get an error when calling the std::pow function:

erasure.cpp: In instantiation of ‘std::vector<_RealType>
derived<T>::do_foo(derived<T>::fwd_iter_type,
derived<T>::fwd_iter_type) [with T = double; derived<T>::fwd_iter_type
= boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::forward_iterator<_iter,
const _t&>, boost::type_erasure::same_type<_t,
boost::type_erasure::deduced<boost::type_erasure::iterator_value_type<_iter>
> > >, _iter>]’:
erasure.cpp:79:1: required from here
erasure.cpp:51:39: error: no matching function for call to
‘pow(boost::type_erasure::rebind_any<boost::type_erasure::concept_interface<boost::type_erasure::assignable<_iter,
_iter>, boost::type_erasure::concept_interface<boost::type_erasure::incrementable<_iter>,
boost::type_erasure::concept_interface<boost::type_erasure::same_type<_t,
_t>, boost::type_erasure::any_base<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::forward_iterator<_iter,
const _t&>, boost::type_erasure::same_type<_t,
boost::type_erasure::deduced<boost::type_erasure::iterator_value_type<_iter>
> > >, _iter> >, _iter, void>, _iter, void>, _iter, void>, const
_t&>::type, std::size_t&)’
             res[i] = std::pow(*first,i)/n;

(The error message continues by listing possible candidates)

Here below is the new code:

*** [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;

struct _t: te::placeholder { };
struct _iter: te::placeholder { };

template <typename T>
class base
{
protected:
    typedef te::any< mpl::vector< te::forward_iterator<_iter, const _t&>,
                                  te::same_type<_t,
te::forward_iterator<_iter, const _t&>::value_type>>,
                     _iter> fwd_iter_type;
public:
    virtual ~base() { }

    template <typename IterT>
    std::vector<T> foo(IterT first, IterT last) const
    {
        return this->do_foo(first, last);
    }
private:
    virtual std::vector<T> do_foo(fwd_iter_type first, fwd_iter_type
last) const = 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
    {
        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] ***

Where am I wrong?

Thank you for your time.

-- 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