長い間、私はstd::vector
とstd::shared_ptr
を組み合わせて使用していました。最近、constオブジェクトへのポインタが必要なときはいつでもstd::shared_ptr<const T>
を使い始めました。 std::shared_ptr<T>
をstd::shared_ptr<const T>
にキャストすると、同じ参照カウンターを共有し、すべてが自然に感じられるため、これはすべて問題ありません。
しかし、std::vector< std::shared_ptr<const T> >
などの構造を使用しようとすると、問題が発生します。簡単にするために、2つの構造を示します。
template <class T>
using SharedPtrVector = std::vector< std::shared_ptr<T> >;
template <class T>
using SharedConstPtrVector = std::vector< std::shared_ptr<const T> >;
問題は、SharedPtrVector
とSharedConstPtrVector
は非常に似ていますが、SharedConstPtrVector
をSharedPtrVector
にキャストできないことです。
したがって、constを正しくしたいときはいつでも、次のような関数を記述します。
void f(const SharedConstPtrVector<T>& vec);
const SharedPtrVector<T>
をf
に渡す方法はありません。
私はこれについてよく考え、いくつかの代替案を検討しました。
変換関数を書く
template <typename T>
SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&);
一般的な形式でコードを書く:
template <typename T>
void f(const std::vector< std::shared_ptr<T> >& vec);
または
template <typename TIterator>
void f(TIterator begin, TIterator end);
std::vector< std::shared_ptr<const T> >
のアイデアを放棄する
1.の問題は、計算のオーバーヘッドとコードの醜さの増加です。一方、2。は、コードに「すべてがテンプレート」のフレーバーを与えます。
私は経験の浅いプログラマーであり、間違った方向に着手したくありません。この問題の経験がある人からアドバイスを聞きたいです。
それらのオブジェクトの明確な所有者を確立するために、デザインを確認することをお勧めします。これは、人々が共有スマートポインターを使用するように導く明確な所有権の欠如です。
Bjarne Stroustrupは、最後の手段としてのみスマートポインターを使用することをお勧めします。彼の推奨事項(最良から最悪)は次のとおりです。
Bjarne Stroustrup-The Essence of C++:With Examples in C++ 84、C++ 98、C++ 11、and C++ 14 at0:37:40を参照してください。
1この問題はshared_ptr<>
とは関係ありませんが、通常のポインターではすでに発生しています。
template<typename T>
void foo(std::vector<const T*>);
int a,b;
std::vector<int*> bar={&a,&b};
foo<???>(bar); // no value for ??? works
2構成vector<shared_ptr<T>>
は、オブジェクトが保持する所有者がいない場合にのみ意味があります。
これは、不変の(したがってスレッドセーフな)オブジェクトを格納する有効な方法であり、要素ごとのコピーオンライトキャッシュの構成要素です。間違いなくアンチパターンではありません。
std::vector
を維持することを主張する場合は、ハンドル本体のイディオム構造にカプセル化することができます。
これにより、const
以外の共有ポインタをconst
ハンドルに保持できます。