使用boost :: bind和boost :: static_pointer_cast转换boost :: shared_ptr的向量

时间:2013-07-10 21:43:54

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

我有一个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<A> elem,可以使用boost::static_pointer_cast<B>(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一起使用。 Mi尝试包括:

//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(<unresolved overloaded function type>, boost::arg<1>& )"

有什么想法吗?


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

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

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

2 个答案:

答案 0 :(得分:3)

通常可以通过指定所需的函数指针类型来告诉编译器您需要哪个重载。

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() );

答案 1 :(得分:0)

我不确定你为什么在第二次尝试时遇到这个错误,因为那个应该有效。

但是,如果它是空的,你有可能超出targetVec的范围,因为只需将迭代器传递给transform是不够的,你需要push_back结果演员阵容targetVec。这可以通过将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 ) );
}