转换矢量<boost :: shared_ptr <foo>&gt; to vector <foo *>,是否可能?</foo *> </boost :: shared_ptr <foo>

时间:2012-12-09 12:53:51

标签: c++ boost shared-ptr

我有一个函数,它接受一个指向Foo的stl向量作为参数。

但是,我也有对象是同一个类Foo的共享指针。我希望能够调用此函数来提供其他对象。我是否必须重载该功能?我似乎无法将其从vector<shared_ptr<Foo>>动态投射到vector<Foo*>

我知道可以使用Get()方法将shared_ptr转换为指针,但是这个呢?有什么想法吗?

更新问题

我已经实现了下面建议的解决方案,但现在,在声明模板函数的所有可能类型时,我得到:

“void my_func(std :: vector&amp;,std :: vector&amp;)的显式实例化[与Ptr_Jet1 = Jet *,Ptr_Jet2 = Jet *]'但没有定义”

和所有其他组合相同(例如,Ptr_Jet1是shared_ptr而不是Jet *。

在.cpp文件中,我有:

template<typename Ptr_Jet1, typename Ptr_Jet2>
void my_func(vector<Ptr_Jet1> vec1, vector<Ptr_Jet2> vec2){
//definition
}

在.h文件中,我有:

typedef boost::shared_ptr<Jet> ptr_jet;

template<typename Ptr_Jet1, typename Ptr_Jet2>
void my_func(vector<Ptr_Jet1> vec1, vector<Ptr_Jet2> vec2);
//
template void my_func(vector<Jet*> vec1, vector<Jet*> vec2);
template void my_func(vector<Jet*> vec1, vector<ptr_jet> vec2);
template void my_func(vector<ptr_jet> vec1, vector<Jet*> vec2);
template void my_func(vector<ptr_jet> vec1, vector<ptr_jet> vec2);

我不明白这里有什么不对......

2 个答案:

答案 0 :(得分:4)

shared_ptr<T>T*是不同的类型,因此您不能简单地从vector<shared_ptr<T>>投射到vector<T*>。如果你确实需要一个vector<T*>(意思是根据Barnabas Szabolcs的答案你无法改变你的功能),你需要手动将指针复制出源向量。既然你正在使用boost,我认为使用Boost.Range是可以的。如果你可以使用C ++ 11,这很简单:

vector< shared_ptr<Foo> > foo;
auto range = foo | boost::adaptors::transform([](shared_ptr<Foo>& ptr) { return ptr.get(); };
std::vector<Foo*> bar(range.begin(), range.end());

这使用C ++ 11作为lambda函数(可以很容易地用c ++ 03代码的functor / functionptr替换)和auto来保存范围。 IIRC Boost.Range的文档中未指定范围转换的返回类型,因此对其进行硬编码可能是一个坏主意。要删除c ++ 03代码中的auto,可以使用boost::copy_range

struct transformation //using a functor instead of a plain function will enable inlining of the transformation, which is liekly benefitial for performance
{ Foo* operator()(shared_ptr<Foo>& ptr) { return ptr.get();}};

std::vector<Foo*> bar = boost::copy_range<std::vector<Foo*>>(foo | boost::adaptors::transform(transformation()));

当然,您可以使用transform_iterator中的Boost.Iterators,但我发现使用Range可以获得更易读的代码。

当然,如果您仅将vector<Foo*>用作函数的参数,则可以跳过将其写入变量并直接调用myFunc(copy_range<std::vector<Foo*>>(...)),这可能会使编译器跳过几个副本

答案 1 :(得分:3)

如果您编写了该函数,我建议使用模板化,因为shared_ptr有operator*,就像使用原始指针一样。

template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& ); // or something alike here

在这种情况下,模板化与函数重载基本相同,但是通过模板化可以避免重复代码。

如果您无法控制该功能,则需要转换整个矢量。如果它不超过1000个元素并且你不会超过几百次,那么恐怕没有太多的性能损失。

不幸的是,你不能将它们动态地转换为另一个,因为它们与继承无关。虽然它们看起来很相似,但vector<T>vector<U>无关。

更新:
我同意Grizzly,模板参数会自动推断出来,所以你不需要明确地写出来。所以你可以继续称它为your_fun(v)

您唯一需要注意的事项是:如果您单独处理标题和代码文件,则需要explicitly instruct the compiler that it should create both of your functions,如下所示:

//header file:

template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& ); 

template void your_fun(const vector<Foo*>& ); 
template void your_fun(const vector<shared_ptr<Foo> >& ); 

//code file:

template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& )
{
  // implementation
}

UPDATE2 :(回答Elelias'es评论)

您的模板声明应如下所示:

// header file:

template<typename _Tp1, typename _Tp2, typename _Tp3>
void your_fun(const vector<_Tp1>&, const vector<_Tp2>&, const vector<_Tp3>& ); 

之后,您有两个选择:

  1. 您可以将定义放入单独的代码文件中。在这种情况下,您需要在标题的实施文件中有6个显式模板实例化,每个组合一个。

  2. 您可以将定义放入标题,然后您不需要6个显式实例化。在这种情况下,我宁愿建议这样做。虽然它没有单独声明和实现,但它并不是那么糟糕的解决方案。我也在严肃的c ++库中看到过这种方法,作为一个例子,你可以看看OpenCV中的operations.hpp。