0

我有一个指向对象的 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。小米尝试包括:

//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

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

4

2 回答 2

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() );
于 2013-07-10T23:04:31.353 回答
0

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

但是,如果它为空,您可能会超出界限,targetVec因为仅将迭代器传递给transform是不够的,您需要push_back将结果转换为targetVec. 这可以通过传递 a back_insert_iteratorto轻松完成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 ) );
}
于 2013-07-10T22:36:09.040 回答