Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type-erased C++ output iterator

How to erase type from output iterators as std::insert_iterator and std::back_insert_iterator? Is it possible to use boost any_iterator to do so?

#include <boost/range.hpp>
#include <boost/range/detail/any_iterator.hpp>
#include <vector>

typedef boost::range_detail::any_iterator<
    int, boost::incrementable_traversal_tag, int &, std::ptrdiff_t > It;

int main()
{
    std::vector<int> v;
    It outIt( v.begin() ); // compiles
    It inserter( std::back_inserter(v) ); // does not compile
    return 0;
}
like image 349
Michal Čizmazia Avatar asked May 29 '12 06:05

Michal Čizmazia


2 Answers

any_iterator is not designed for use with output iterators, which is what back_insert_iterator is (or, for that matter, input iterators).

back_insert_iterator is defined to inherit from iterator<output_iterator_tag, void, void, void, void> i.e. its value_type, reference_type, distance_type and pointer_type are all void, but any_iterator expects to be able to indirect through its backing iterator to a non-void value. Perhaps it would be better named any_value_iterator; but then it is a detail class template.

like image 180
ecatmur Avatar answered Sep 20 '22 01:09

ecatmur


So I implemented my own one using Boost.

#include <boost/function_output_iterator.hpp>
#include <boost/function.hpp>

template < class T >
class AnyInserter : public boost::function_output_iterator< boost::function< void ( const T & value ) > >
{
private:
    typedef typename boost::function_output_iterator< boost::function< void ( const T & value ) > > BaseType;
    template < class OutIt > struct Insert
    {
        Insert( OutIt it ) : m_it(it) {}
        void operator () ( const T & value ) { m_it++ = value; }
        OutIt m_it;
    };
public:
    template < class OutIt >
        explicit AnyInserter( const OutIt & it ) : BaseType( Insert< OutIt >(it) ) {}
};

template < class OutIt >
    inline AnyInserter< typename OutIt::container_type::value_type >
    makeAnyInserter( const OutIt & it ) 
    {
        return AnyInserter< typename OutIt::container_type::value_type >(it);
    }
like image 29
Michal Čizmazia Avatar answered Sep 21 '22 01:09

Michal Čizmazia