![](/img/trans.png)
[英]C++ Passing std::vector< boost::shared_ptr< foo > >
[英]convert vector<boost::shared_ptr<Foo> > to vector<Foo*> , is it possible?
我有一個函數,將指向Foo的指針的stl向量作為參數。
但是,我也有一些對象,它們是指向同一類Foo的共享指針。 我也希望能夠調用此函數來提供其他對象。 我是否需要重載該功能? 我似乎無法將其從vector<shared_ptr<Foo>>
動態vector<shared_ptr<Foo>>
到vector<Foo*>
。
我知道可以使用Get()方法將shared_ptr轉換為指針,但是那又如何呢? 有任何想法嗎?
有關問題的更新 :
我已經實現了下面建議的解決方案,但是現在,當聲明模板函數的所有可能類型時,我得到:
“'void my_func(std :: vector&,std :: vector&)[帶有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);
我不明白這是怎么回事...
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函數(可以很容易地用functor / functionptr替換c ++ 03代碼)並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()));
當然,您可以改用Boost.Iterators
的transform_iterator
,但是我發現使用Range
使代碼更易讀。
當然,如果僅將vector<Foo*>
用作函數的參數,則可以跳過將其寫入變量的操作,而直接調用myFunc(copy_range<std::vector<Foo*>>(...))
,這可能會使編譯器跳過一些副本。
如果您編寫了該函數, 我建議您進行模板化 ,因為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)
。
唯一需要注意的是:如果分別處理頭文件和代碼文件,則需要明確指示編譯器應創建兩個函數 ,如下所示:
//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的評論)
您的模板聲明應如下所示:
// header file:
template<typename _Tp1, typename _Tp2, typename _Tp3>
void your_fun(const vector<_Tp1>&, const vector<_Tp2>&, const vector<_Tp3>& );
之后,您有2個選項:
您可以將定義放入單獨的代碼文件中。 在這種情況下, 實現文件中的標頭需要6個顯式模板實例,每個組合一個。
您可以將定義放入標頭中 ,然后不需要6個顯式實例化。 在這種情況下,我寧願建議這樣做。 盡管它沒有將聲明和實現分開,但它並不是一個糟糕的解決方案。 我在嚴肅的c ++庫中也看到了這種方法,例如,您可以查看OpenCV中的operation.hpp。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.