2016-10-28 41 views
0

我正在實現指針的自定義向量my_ptr_vector使容器協變

我有一個類BaseDerived派生Base

我有一個方法,該方法應該在my_ptr_vector<Base>my_ptr_vector<Derived>上都起作用(通過const引用!)。它只調用Base課程中的元素方法。

然而,編譯器會抱怨它沒有轉化成my_ptr_vector<Derived>my_ptr_vector<Base>方式。

小例子,再現問題:

#include <vector> 
#include <memory> 

class Base {}; 
class Derived : public Base {}; 

template<typename Element> 
class my_ptr_vector : public std::vector< std::unique_ptr<Element> > {}; 

void funct(const my_ptr_vector<Base>& vect) {} 

int main() 
{ 
    my_ptr_vector<Derived> vect; 
    funct(vect); 
} 

錯誤:

no suitable user-defined conversion from "my_ptr_vector<Derived>" to "const my_ptr_vector<Base>" exists 

我發現here,我可以做,如果我從my_ptr_vector<U>提供一個構造函數和賦值運算符它的工作,用U通用的,這樣U*可以轉換爲T*

事實上,如果在例子中,我改變類此,它的工作原理

template<typename Element> 
class my_ptr_vector : public std::vector< std::shared_ptr<Element> > { 
public: 
    my_ptr_vector() {} 

    ///copy constructor from vector of pointers to generic U 
template<typename DerivedElement> 
    my_ptr_vector(const my_ptr_vector<DerivedElement>& oth) 
    { 
     printf("Oh, noes!"); //we don't want this method executed! 

     resize(oth.size()); 

     for (std::shared_ptr<Element> ptr : oth) 
     { 
      push_back(ptr); 
     } 
    } 
}; 

然而,中 - 它不只是一個暗示,它不應該擔心的構造函數執行print聲明;它實際上是在執行轉換!

有沒有辦法避免這種情況?

另一種可能的解決方法當然是做func模板:

template<typename T> 
    void funct(const my_ptr_vector<T>& vect) {} 

然而,這種方式我失去裏面funcvect元素是Base類型始終的信息。

+2

如果您向我們展示代碼([mcve]),會更容易。我的第一個想法是使用'my_ptr_vector ',這是處理其中一些派生類的向量的常用方法。 –

+0

也許你正在尋找[std :: unique_ptr](http://en.cppreference)的一個很好的[std :: vector](http://en.cppreference.com/w/cpp/container/vector)。 com/w/cpp/memory/unique_ptr)或[std :: shared_ptr](http://en.cppreference.com/w/cpp/memory/shared_ptr)? –

+0

@TopologicalSort你是對的,做:) –

回答

0

這似乎是做你想做的。代碼的第二部分,copy ctor,不需要修改。

我不認爲你可以擺脫需要投到std::unique_ptr。它希望即使這是推動Base*

#include <vector> 
#include <memory> 

class Base {}; 
class Derived : public Base {}; 

template<typename Element> 
class my_ptr_vector : public std::vector< std::unique_ptr<Element> > {}; 

void funct(const my_ptr_vector<Base>& vect) {} 

int main() 
{ 
    my_ptr_vector<Base> vect; 
    vect.push_back(std::unique_ptr<Base>(new Derived)); 

    funct(vect); 
} 
+0

是這編譯;但我會失去調用Derived-only方法的可能性,我需要這種方法。 –

+0

@FrancescoDondi不,你不會 - 這是'dynamic_cast' /'static_cast'是爲... –

+0

Mhh是的,你是對的,但它很醜。而不是在'func'裏面記住類型是'Base'而不是'T',我不得不在外面記住類型是'Derived'而不是'Base' ......我想要的是將類型轉換爲'在編譯器上檢查onus。 –