Domanda

Voglio creare una funzione che può assumere diversi tipi di iteratori che memorizzano lo stesso tipo di oggetto:
Il primo è un contenente std::map shared_ptr<Foo> (typedef-cata FooMap) e l'altro è un std::list che contiene anche shared_ptr<Foo> (FooList).

Mi piace molto le MSalters soluzione suggerita per una domanda simile e hanno cercato di implementare iteratori boost::variant , che la funzione otterrà come parametri per iterare dal primo al secondo.

La mia funzione simile a questa (semplificato un bel po '):

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

Il FooIterator ei visitatori sono definiti come segue:

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

ho ottenuto la maggior parte del al distacco di questa mail . Tale soluzione utilizza anche gli adattatori e politiche, che sembra essere un po 'troppo, a seconda della risposta del MSalters, quindi non voglio semplicemente copiare il codice. Tanto più che ho capito solo una parte di esso.

Con il codice sopra ottengo il seguente errore del compilatore da VS2008 (questo è solo le prime righe di 160 in totale, che credo sia un po 'troppo a postare qui, ma sarò felice di aggiungerli Se qualcuno vuole vedere tutto):

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>        ]
[...]

Che cosa sto facendo di sbagliato?

È stato utile?

Soluzione

Ho il sospetto che non trovi il caso sul vostro static_visitor do_compare. Ricordate, le varianti potrebbe avere qualsiasi cosa, quindi è necessario tutte le combinazioni possibili, come paragonare un FooList :: const_iterator ad un FooMap :: const_iterator. Si lamenta perché il compilatore sta cercando di trovare un po 'di corrispondenza per quel caso, e non è in grado di convertire un FooMap :: const_iterator ad un FooList :: const_iterator.

martellare out:

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

Ecco una versione con i modelli:

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

E 'la compilazione on Comeau, ma non sono al 100% che funzionerà, quindi è necessario un po' di test. Altro che più pulito, il codice più versatile, non dovrebbe avere alcun effetto, a patto che funziona.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top