Frage

Ich möchte eine Funktion erstellen, die verschiedene Arten von Iteratoren nehmen können, die die gleiche Art von Objekt speichern:
Die erste ist eine std::map enthält shared_ptr<Foo> (typedef-ed als FooMap) und das andere ist ein std::list die auch shared_ptr<Foo> (FooList) enthält.

Ich mag die Lösung MSalters für eine ähnliche Frage vorgeschlagen und versucht boost::variant Iteratoren zu implementieren , die die Funktion als Parameter erhalten wird aus dem ersten in den zweiten iterieren.

Meine Funktion sieht wie folgt aus (vereinfacht ziemlich viel):

set<Foo> CMyClass::GetUniqueFoos(FooIterator itBegin, FooIterator itEnd)
{
    set<Foo> uniques;
    for(/**/;
        apply_visitor(do_compare(), itBegin, itEnd);  // equals "itBegin != itEnd"
        apply_visitor(do_increment(), itBegin))       // equals "++itBegin"
    {
        // Exact mechanism for determining if unique is omitted for clarity
        uniques.insert( do_dereference< shared_ptr<Foo> >(), itBegin) );
    }

    return uniques;
}

Die FooIterator und die Besucher sind wie folgt definiert:

typedef
    boost::variant<
        FooMap::const_iterator,
        FooList::const_iterator>
    FooIterator;

struct do_compare : boost::static_visitor<bool>
{
    bool operator() (
        const FooMap::const_iterator & a,
        const FooMap::const_iterator & b) const
    { return a != b; }

    bool operator() (
        const FooList::const_iterator & a,
        const FooList::const_iterator & b) const
    { return a != b; }
};

struct do_increment: boost::static_visitor<void>
{
    template<typename T>
    void operator()( T& t ) const
    { ++t; }
};

template< typename Reference >
struct do_dereference: boost::static_visitor<Reference>
{
    template<typename T>
    Reference operator()( const T& t ) const
    { return *t; }
};

Ich habe die meisten der oben von Anhang dieser Mail . Diese Lösung nutzt auch Adapter und Richtlinien, die ein wenig zu viel, nach der Antwort von MSalters zu sein scheint, so will ich nicht einfach diesen Code kopieren. Vor allem, weil ich nur einen Teil davon zu verstehen.

Mit dem obigen Code, den ich die folgenden Compiler-Fehler von VS2008 (dies ist nur die ersten Zeilen von 160 insgesamt, was ich denke, ist ein bisschen zu viel hier posten, aber ich bin glücklich, sie zu addieren, wenn jemand will alles) sehen:

1>c:\boost\boost\variant\detail\apply_visitor_binary.hpp(63) :
 error C2664: 'bool CMyClass::do_compare::operator ()(
 const std::list<_Ty>::_Const_iterator<_Secure_validation> &,
 const std::list<_Ty>::_Const_iterator<_Secure_validation> &) const' :
 cannot convert parameter 1 from 'T0' to
 'const std::list<_Ty>::_Const_iterator<_Secure_validation> &'
1>        with
1>        [
1>            _Ty=shared_ptr<Foo>,
1>            _Secure_validation=true
1>        ]
1>        Reason: cannot convert from 'T0' to 'const std::list<_Ty>::_Const_iterator<_Secure_validation>'
1>        with
1>        [
1>            _Ty=shared_ptr<Foo>,
1>            _Secure_validation=true
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>        c:\boost\boost\variant\variant.hpp(806) : see reference to function template instantiation 'bool boost::detail::variant::apply_visitor_binary_invoke<Visitor,Value1>::operator ()<T>(Value2 &)' being compiled
1>        with
1>        [
1>            Visitor=const CMyClass::do_compare,
1>            Value1=T0,
1>            T=T1,
1>            Value2=T1
1>        ]
[...]

Was mache ich falsch?

War es hilfreich?

Lösung

Ich vermute, Sie Fälle auf Ihrer do_compare static_visitor fehlen. Denken Sie daran, könnten die Varianten etwas haben, so müssen Sie alle möglichen Kombinationen, wie ein FooList :: const_iterator zu einem FooMap :: const_iterator vergleicht. Es beschwert, weil der Compiler für diesen Fall eine Übereinstimmung zu finden versucht, und kann keine FooMap konvertieren :: const_iterator zu einem FooList :: const_iterator.

Hammern es aus:

struct do_compare : boost::static_visitor<bool>
{
    bool operator() (
        const FooMap::const_iterator & a,
        const FooMap::const_iterator & b) const
    { return a != b; }

    bool operator() (
        const FooList::const_iterator & a,
        const FooList::const_iterator & b) const
    { return a != b; }

    bool operator() (
        const FooMap::const_iterator & a,
        const FooList::const_iterator & b) const
    { return false; }

    bool operator() (
        const FooList::const_iterator & a,
        const FooMap::const_iterator & b) const
    { return false; }
};

Hier ist eine Version mit Vorlagen:

template <typename A, typename B>
bool operator() (
    const A & a,
    const B & b) const
{ return false; }

template <typename A>
bool operator() (
    const A & a,
    const A & b) const
{ return a != b; }

Es ist Kompilieren auf comeau, aber ich bin nicht zu 100% wird es funktionieren, so dass einige Tests erforderlich. Anders als sauberer, vielseitiger Code, sollte es keine Auswirkungen haben, solange es funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top