【问题标题】:"Cannot convert parameter" using boost::variant iterator“无法转换参数”使用 boost::variant 迭代器
【发布时间】:2010-11-01 12:09:16
【问题描述】:

我想创建一个函数,它可以采用不同类型的迭代器来存储相同类型的对象:
第一个是包含shared_ptr<Foo>(类型定义为FooMap)的std::map,另一个是包含shared_ptr<Foo>FooList)的std::list

我真的很喜欢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>        ]
[...]

我做错了什么?

【问题讨论】:

    标签: c++ iterator visual-c++-2008 boost-variant


    【解决方案1】:

    我怀疑您的 do_compare static_visitor 中缺少案例。请记住,变体可能有任何内容,因此您需要所有可能的组合,例如将 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; }
    

    它在 Comeau 上编译,但我不是 100% 会工作,所以需要进行一些测试。除了更干净、更通用的代码之外,它应该不会有任何影响,只要它可以工作。

    【讨论】:

    • 太好了,行得通!谢谢!我不知道你为什么用模板删除评论。使用它们有什么副作用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多