2012-05-29 17 views
6

Jak wymazać typ z wyjściowych iteratorów jako std::insert_iterator i std::back_insert_iterator? Czy możliwe jest użycie doładowania any_iterator?iterator wyjścia C++ z wymazaną czcionką

#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; 
} 
+0

Co masz na myśli przez "wymazać typ"? –

+0

@EitanT: Powinieneś sprawdzić "C++ type erasure", ale dla krótkiej definicji "proces przekształcania wielu typów ze wspólnym interfejsem w jeden typ z tym samym interfejsem". Boost :: Any będzie przykładem kanonicznym. –

+0

@JesseDobra Aaa Wiem, co to jest, nigdy nie wiedziałem, że nazywa się "typ wymazania". Doh! –

Odpowiedz

6

any_iterator nie jest przeznaczony do stosowania z iteratorów wyjściowych, który jest co back_insert_iterator jest (lub, jeśli o to chodzi, wejściowe iteratory).

back_insert_iterator definiuje dziedziczyć iterator<output_iterator_tag, void, void, void, void> czyli jej value_type, reference_type, distance_type i pointer_typevoid, ale any_iterator oczekuje, że będzie w stanie pośrednim poprzez podłoża do iteracyjnej bez pustych przestrzeni wartości. Być może byłoby lepiej o nazwie any_value_iterator; ale jest to szablon klasy detail.

+0

Dziękuję. Czy są jakieś alternatywy w Boost? –

+0

Nie, że jestem świadomy; Problem polega na tym, że 'boost :: iterator_facade' spodziewa się, że będzie w stanie zdefiniować' operator [] 'i' operator-> 'w klasie. Nie powinno być zbyt trudno zdefiniować siebie za pomocą 'boost :: function', aby owinąć' operator = '(która jest jedyną częścią iteratora wyjścia, która ma znaczenie). – ecatmur

3

Więc zaimplementowałem swój własny przy użyciu funkcji 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); 
    } 
+2

To wygląda dobrze. Jedną z kwestii jest to, że zamiast 'nazwa_typu OutIt :: typ_konbioru :: typ_wartości' możesz chcieć użyć' typename std :: iterator_traits :: value_type', dzięki czemu możesz użyć swojego szablonu np. surowe wskaźniki. – ecatmur