簡體   English   中英

轉換向量 <boost::shared_ptr<Foo> &gt;到矢量 <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.Iteratorstransform_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個選項:

  1. 您可以將定義放入單獨的代碼文件中。 在這種情況下, 實現文件中的標頭需要6個顯式模板實例,每個組合一個。

  2. 您可以將定義放入標頭中 ,然后不需要6個顯式實例化。 在這種情況下,我寧願建議這樣做。 盡管它沒有將聲明和實現分開,但它並不是一個糟糕的解決方案。 我在嚴肅的c ++庫中也看到了這種方法,例如,您可以查看OpenCV中的operation.hpp。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM