2009-06-09 8 views
3

Я хочу создать функцию, которая может принимать различные типы итераторов, которые сохраняют один и тот же тип объекта:
Первым является std::map содержащим shared_ptr<Foo> (ЬурейеГо-й изда как FooMap), а другой - std::list, который также содержит shared_ptr<Foo> (FooList).«Не удается преобразовать параметр» используя подталкивание :: варианта итератор

Мне очень понравился the solution MSalters suggested for a similar question и попытался реализовать итераторы boost::variant, которые функция получит как параметры для итерации от первой до второй.

Моя функция выглядит следующим образом (упрощенно совсем немного):

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

FooIterator и посетители определяются следующим образом:

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

я получил большую часть выше from the attachment of this mail. В этом решении также используются адаптеры и политики, которые, как представляется, слишком много, в соответствии с ответом MSalters, поэтому я не хочу просто копировать этот код. Тем более, что я только понимаю часть этого.

С приведенным выше кодом я получаю следующую ошибку компилятора от VS2008 (это всего лишь первые несколько строк из 160, что, я думаю, слишком много для публикации здесь, однако я буду рад добавить их Если кто-то хочет увидеть все это):

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

Что я делаю неправильно?

ответ

6

Я подозреваю, что вам не хватает случаев на вашем статическом_визере do_compare. Remeber, варианты могут иметь что угодно, поэтому вам нужны все возможные комбинации, например сравнение FooList :: const_iterator с FooMap :: const_iterator. Он жалуется, потому что компилятор пытается найти некоторое совпадение для этого случая и не может преобразовать FooMap :: const_iterator в FooList :: const_iterator.

ударное это:

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

Вот версия с шаблонами:

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

Это компилируется на Комео, но я не 100% он будет работать, так что требуется некоторое тестирование. Помимо более чистого, более универсального кода, он не должен иметь никакого эффекта, если он работает.

+0

Отлично, это работает! Благодаря! Я не знаю, почему вы удалили комментарий с шаблонами. Есть ли побочные эффекты для их использования? – foraidt