Question

Je veux créer une fonction qui peut prendre différents types d'itérateurs qui stockent le même type d'objet:
Le premier est un std::map contenant shared_ptr<Foo> (typedef-ed comme FooMap) et l'autre est un std::list qui contient également shared_ptr<Foo> (FooList).

Je aime vraiment la solution MSalters suggéré pour une question similaire et ont essayé de mettre en œuvre itérateurs boost::variant , que la fonction s'en tant que paramètres pour itérer de la première à la seconde.

Ma fonction ressemble à ceci (simplifié un peu):

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

Le FooIterator et les visiteurs sont définis comme suit:

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

Je suis plus de ce qui précède de la pièce jointe de ce mail . Cette solution utilise également des adaptateurs et des politiques, ce qui semble être un peu trop, selon la réponse de MSalters, donc je ne veux pas simplement copier ce code. D'autant plus que je comprends seulement une partie.

Avec le code ci-dessus je reçois l'erreur du compilateur suivant de VS2008 (ce sont seulement les premières lignes de 160 au total, ce qui je pense est un peu trop à poster ici, mais je serai heureux de les ajouter Si quelqu'un veut tout voir):

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

Qu'est-ce que je fais mal?

Était-ce utile?

La solution

Je suppose que vous êtes sur votre cas manquent do_compare static_visitor. Remeber, les variantes pourrait avoir quelque chose, vous devez donc toutes les combinaisons possibles, comme la comparaison d'un FooList :: const_iterator à un FooMap :: const_iterator. Il se plaint parce que le compilateur essaie de trouver un match pour la ce cas, et ne peut pas convertir un FooMap :: const_iterator à un FooList :: const_iterator.

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

Voici une version avec des modèles:

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

Il est sur la compilation comeau, mais je ne suis pas 100% cela va fonctionner, de sorte que certains tests sont nécessaires. Autre que le code plus propre, plus polyvalent, il ne devrait pas avoir d'effet, aussi longtemps que cela fonctionne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top