【问题标题】:Transform vector of boost::shared_ptr using boost::bind and boost::static_pointer_cast使用 boost::bind 和 boost::static_pointer_cast 变换 boost::shared_ptr 的向量
【发布时间】:2013-07-09 00:28:36
【问题描述】:

我有一个指向对象的 Boost 共享指针的 std::vector,并且希望获得一个共享指针的向量,该向量指向被转换为更具体类型的相同对象:

//using boost::shared_ptr, std::vector;
vector<shared_ptr<A> > originalVec;
vector<shared_ptr<B> > targetVec( originalVec.size() ); // B extends A

对于单个元素shared_ptr&lt;A&gt; elem,可以使用boost::static_pointer_cast&lt;B&gt;(elem) 对其进行强制转换,其语法复制如下(来自Boost shared_ptr doc):

template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

我不知道如何将它与std::transform 一起使用。尝试包括:

//using boost::bind, boost::static_pointer_cast
transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( static_pointer_cast<B>, _1) )
transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( static_pointer_cast<B,A>, _1) ) 

在这两种情况下都获得"no matching function for call to bind(&lt;unresolved overloaded function type&gt;, boost::arg&lt;1&gt;&amp; )"

有什么想法吗?


编辑: 该问题可能与歧义有关,因为为侵入式指针类定义了类似的函数模板,语法:

template<class T, class U>
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws

在这种情况下,问题是如何指定第一个参数的类型,以便编译器知道选择哪个方法。

【问题讨论】:

    标签: c++ boost stl shared-ptr boost-bind


    【解决方案1】:

    你通常可以通过指定你想要的函数指针的类型来告诉编译器你想要哪个重载,例如

    typedef shared_ptr<B>(*func_type)(const shared_ptr<A>&);
    
    transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( (func_type)static_pointer_cast<B,A>, _1) );
    

    但是,如果您从无法消除歧义的重载函数中得到这种错误,我首选的解决方案通常是提供一个执行调用的自定义函子,以便编译器完成重载解析,并且您不必选择重载,例如

    struct Downcast {
      shared_ptr<B> operator()(const shared_ptr<A>& p) const
      { return shared_pointer_cast<B>(p); }
    };
    
    transform( originalVec.begin(), originalVec.end(), targetVec.begin(), Downcast() );
    

    【讨论】:

    • 这里是第二种情况:无法解决歧义。我使用转换来避免编写循环......从这个意义上说,必须创建一个仿函数破坏了我所想到的简洁性(甚至比循环更多的代码!!)。很遗憾我们在 C++98 中没有 lambda 表达式 :P 谢谢你的帮助!
    • Ooook,没有其他令人满意的解决方案,所以我接受你的。最后使用了一个简单的“for”循环。啊啊C++,你这个无情的混蛋。
    【解决方案2】:

    我不确定您为什么在第二次尝试时遇到了这个错误,因为那个应该可以工作。

    但是,如果 targetVec 为空,则可能会超出其范围,因为仅将迭代器传递给 transform 是不够的,您需要将 push_back 转换为 @987654325 的结果@。这可以通过将back_insert_iterator 传递给transform 轻松完成。

    int main()
    {
        std::vector<boost::shared_ptr<A>> original;
        std::vector<boost::shared_ptr<B>> target;
    
        original.push_back( boost::make_shared<B>() );
    
        boost::transform( original,
                          std::back_inserter( target ),
                          boost::bind( boost::static_pointer_cast<B, A>, _1 ) );
    
        // OR
        std::transform( original.begin(), 
                        original.end(),
                        std::back_inserter( target ),
                        boost::bind( boost::static_pointer_cast<B, A>, _1 ) );
    }
    

    【讨论】:

    • 是的,我对第二次尝试不起作用感到特别恼火。感谢您的建议,但事实并非如此:我只是忘了说第二个数组保留了足够的空间 --declared as vector > targetVec( originalVec.size() );
    猜你喜欢
    • 2023-04-03
    • 2012-09-27
    • 2016-03-16
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多