2016-10-28 3 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); 
} 

エラー:私はUで、私はmy_ptr_vector<U>からコンストラクタと代入演算子を提供した場合にそれを動作させることができhereを発見した

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

一般的なので、U*T*に変換できます。例では、私はこれにクラスを変更した場合

は確かに、それはそれはそれが心配べきではないということだけヒントはありません-itコンストラクタでprintステートメントを実行しない、しかし

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); 
     } 
    } 
}; 

作品;それは実際に変換を実行しています!

これを回避する手段はありますか?

別の可能な解決策はfuncは、テンプレート作成することはもちろんです:

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

しかし、私はfunc内という情報が失われ、このように、vectの要素は常にタイプ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

これはあなたが望むことをするようです。コードの第2部分(コピー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

はいと思われるあなたのユースケース 'funct'の拡張情報なしこれはコンパイルされます。私はDerived-onlyメソッドを呼び出す可能性を失います。私はそれを必要とします。 –

+0

@FrancescoDondiあなたはそうではありません - これは 'dynamic_cast' /' static_cast'が作られたものです... –

+0

あなたは正しいですが、それは醜いです。型が 'T'ではなく' Base'であることを覚えておく必要があるのではなく、型が 'Base'ではなく' Derived'であることを覚えていなければなりません...私が望むのは、コンパイラのonusをチェックします。 –

関連する問題