2016-09-01 9 views
7

>(別の例):私は コピーベクトル<shared_pt<T>>私はC++

std::vector<std::shared_ptr<const T>> 

にコピーしたい

std::vector<std::shared_ptr<T>> 

は、今私がいることに気づいた場合、私これを行う:それは罰金コンパイル

class A 
{ 
public: 
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(list.begin(), list.end()) {} 
    std::vector<std::shared_ptr<const int>> internalList; 
}; 

(打ち鳴らす++のstdを== C++ 14)が、私がしなければ:

class A 
{ 
public: 
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(list) {} 
    std::vector<std::shared_ptr<const int>> internalList; 
}; 

コピーコンストラクタを使用すると、非constからconstへの変換がわからないため、コピーコンストラクタを使用すると機能しません。

xxxx.cpp:672:56: error: no matching constructor for initialization of 'std::vector<std::shared_ptr<const int> >' 

なぜしてください誰かが説明し、私は(コンストラクタでイテレータを使用して)それを行う方法が最善の解決策である場合にもらえますか?

std::vectorが変換コンストラクタを提供した場合にあなたのコードは、仕事ができる
+1

非constからconstへの変換(つまり、intからconst intへの変換)だったら問題ありません。しかし、それはここで起こっていることではなく、あるタイプのオブジェクトから完全に異なるタイプのオブジェクトへの変換です。そして、コピーコンストラクタは引数として独自の型だけを取ります。異なる型ではありません。 –

+0

それは意味がありますが、この作品のようなものではないでしょうか? 'int a = 1; const int b = a'?だから私の質問は、この割り当てが働いている理由とコピーコンストラクタを使用してこれを行うことができないのですか?私は本当にこれをやめることから何が止まっているのか不思議です。私はそれが最適化の理由で行われていないと仮定します... – user18490

+1

@ user18490 'const std :: vector 'は 'std :: vector 'と同じではありません。したがって、 'int'と' const int'の類推は成立しません。 –

答えて

2

最初に、異なるタイプでインスタンス化されたクラステンプレートはまったく異なるタイプです。 std::shared_ptr<int>std::shared_ptr<const int>はまったく異なるタイプであり、std::vector<std::shared_ptr<int>>std::vector<std::shared_ptr<const int>>も異なるタイプであり、お互いに変換することはできません。

std::vectorによれば、コピーコンストラクタ(5番目のコピーコンストラクタ)は、パラメータと同じ型のstd::vectorをとります。それはstd::vector<std::shared_ptr<const int>>を意味し、std::vector<std::shared_ptr<int>>を取ることができません。暗黙的にstd::vector<std::shared_ptr<const int>>に変換することはできません。

一方、イテレータの範囲(4番目のもの)を取るコンストラクタは関数テンプレートであり、イテレータの型はテンプレートパラメータであり、同じ型を指すイテレータである必要はありません。この型を使ってベクトルを構築することができれば、他の型を指すイテレータであってもかまいません。 std::shared_ptr<const int>を構築するためにstd::shared_ptr<int>を使用すると、それは問題ありません。

std::shared_ptrにはコピー/移動コンストラクタテンプレートがあります。このテンプレートは、異なる要素タイプを引数としてstd::shared_ptrをとることができます。 (std::vectorではありません)

3

template<class T, class A = std::allocator<T>> 
class vector { 
public: 
    template<class T1, class A1> 
    explicit vector(const vector<T1, A1>& other) 
     : vector(other.begin(), other.end()) 
    {} 

    ... 
}; 

しかし、ほぼ同じ効果を導入することによって達成することができますので、あまりにも多くの価値を追加していないすべての標準ライブラリのコンテナで、このようなコンストラクタを持ちますより一般的な目的のcontainer_castユーティリティ(例えば、this answerを参照)。次に、あなたは次のように書くことができます:

class A 
{ 
public: 
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(container_cast(list)) {} 
    std::vector<std::shared_ptr<const int>> internalList; 
}; 
+0

それは上記の答えに良い追加です。ありがとうございました – user18490

+0

'container_cast'実装は、実際のコードでそれを使用する前に、コピーと移動を強制します。 ; - ] – ildjarn

関連する問題