C ++ 11でauto_ptrの廃止の設計変更を処理する方法は?


12

C ++ 11(つまり-std=c++11)でライブラリをテストしています。ライブラリはauto_ptr次のパターンを使用します:

Foo* GetFoo()
{
    autoptr<Foo> ptr(new Foo);

    // Initialize Foo
    ptr->Initialize(...);

    // Now configure remaining attributes
    ptr->SomeSetting(...);

    return ptr.release();
}

C ++ 11は非推奨auto_ptrになったため、それから離れたいと思います。

ただし、コードはC ++ 03とC ++ 11の両方をサポートしているため、ヤンクするほど単純ではありませんauto_ptr。また、ライブラリに外部依存関係がないことにも言及する価値があります。C ++ 03を使用します。Autotools、Cmake、Boostなどを使用しません...

auto_ptrC ++ 03との互換性を維持しながら、C ++ 11 から移行するための設計変更をどのように処理する必要がありますか?


auto_ptrスコープのいずれか(つまりstd::auto_ptr)は、他のネームスペースからスマートポインターを取得する必要がありますか?
ニール

余談として、あなたはフォールドすることをお勧めしますFoo::InitializeFoo::Foo
–MSalters

1
@MSalters-ええ、それはいつも私が少し不快に感じていることの1つです。ライブラリは1990年代に設計されたもので、設計はMFCに似ていたと思います。つまり、低レベルのC ++構造があり、次に「高レベル」のオブジェクト構造がありました。この機能はトレードオフとして使用されたため、クラスには6または12の異なるコンストラクターがありません。(この時点で、私が行ったことは完了し、POD型のメンバー変数がC ++コンストラクターで正常なデフォルトに初期化されるようになりました)。

回答:


13

ほとんどの点で、これstd::unique_ptrはドロップイン(ただし、より安全)に置き換えられているためstd::auto_ptr、コードを(または)のどちらunique_ptrかを使用するように指示する以外に(必要に応じて)コードの変更はほとんど必要ありませんauto_ptr

これを行うにはいくつかの方法があります(それぞれに独自のリストトレードオフがあります)。提供されたコードサンプルを考えると、最初の2つのオプションのいずれかを優先します

オプション1

#if __cplusplus >= 201103L
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif

トレードオフ;

  • auto_ptr名前をグローバル名前空間に導入します。これを独自の「プライベート」名前空間と定義することで軽減できます
  • C ++ 17に移行すると(auto_ptr完全に削除されると思います)、より簡単に検索および置換できます

オプション2

template <typename T>
struct my_ptr {
    #if __cplusplus >= 201103L
    typedef std::unique_ptr<T> ptr;
    #else
    typedef std::auto_ptr<T> ptr;
    #endif
};

トレードオフ;

  • おそらく作業が面倒になり、現在のauto_ptr必要性はコード内で次のように変更する必要があります。my_ptr<T>::ptr
  • 安全性が向上し、名前がグローバル名前空間に導入されなくなりました

オプション3

やや物議をかもしますがstd、ベースとしてクラスを持つことの警告に我慢する準備ができている場合

#if __cplusplus >= 201103L
template <typename T>
using my_ptr = std::unique_ptr<T>;
#else
template <typename T>
class my_ptr : public std::auto_ptr<T> {
  // implement the constructors for easier use
  // in particular
  explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {}
};
#endif

トレードオフ;

  • 仮想ベース(特に非仮想デストラクタ)が予想される場所では、継承されたクラスを使用しないでください。これはケースの問題であるべきではありません-しかし、それに注意してください
  • 繰り返しますが、コードの変更
  • 潜在的な名前空間の不一致-それはすべて、ポインタクラスがどのように使用されるかに依存します

オプション4

ポインターを新しいクラスにラップし、必要な機能をメンバーに集約します

template <typename T>
class my_ptr { // could even use auto_ptr name?
  #if __cplusplus >= 201103L
  std::unique_ptr<T> ptr_;
  #else
  std::auto_ptr<T> ptr_;
  #endif

  // implement functions required...
  T* release() { return ptr_.release(); }
};

トレードオフ;

  • 本当に極端なのは、実装を「スワップ」することだけです

非常に良い答えです。私は実際にそれを少し調査しましたが、あなたは私が試したテストのうち少なくとも3つにヒットしました。(不足しているのはOS XとClang固有のものです。OSXは時々C ++ 03のTR1名前空間を使用するため、この方法を使用する必要があります。名前空間に 'unique_ptr'という名前の型はありませんLLVM / Clangでコンパイルする場合の「std」)。

@jww。OS X(XCode 6.4およびApple LLVMバージョン6.1.0(clang-602.0.53)(LLVM 3.6.0svnに基づく))を使用しており、tr1名前空間以外のC ++ 03/11ミックスに問題はありませんより長くそこにいます(libstdc ++ではなくlibc ++を使用しています)。tr1が非規範的であることは知っていますが、ドラフト(ここ)にはファイルが必要であることがまったくわかりません<tr1/...>。実際には、ヘッダー<memory>などのtr1名前空間にあるファイルにのみ言及しています。
ニール

@jww。コンパイラ、ライブラリ、およびターゲットデバイスの特定の組み合わせを考えると、もう少し手を立てる必要があるかもしれません。それ以外の場合、OS Xでは、clangとlibc ++への移行を検討してください。率直に言って、私はlibc ++をOS Xの新しい「ネイティブ」C ++ライブラリであると考えています-私はそれをデフォルトにします。私はこれらの主張をサポートする方法がありません。clang/ Apple関係の歴史とOS XのGCCツールが時代遅れ(ライブラリー)であるか、削除された(GCCはclangの薄いスタブである限り) )。
ニール

「その他、OS Xでは、clangとlibc ++に移行することを検討してください...」 -はい、私はあなたに同意します。ただし、ユーザーに選択を許可し、強制するのではありません。(指定する(または指定しない)ときに暗黙的に選択を行いますCXX=...)。

OS X 10.7および10.8で非常に多くのトラブルを引き起こしているケースは次のとおりc++ -v -std=c++11 -x c++ - < /dev/nullです。I grep'dダンプされたディレクトリが含まれ、そして、彼らはないではない含めますunique_ptr

0

オプション5:直接エイリアス。

#if __cplusplus >= 201103L
template<typename T> 
using MyPtr = std::unique_ptr<T>;
#else 
#define MyPtr std::auto_ptr
#endif 

トレードオフ:

  1. C ++ 11以降の新しい言語バージョンでは、エイリアスタイプが正しいスマートポインターにマップされます。実際にstd :: auto_ptrに固有のAPIに依存するユーザーコードは、コンパイラによってフラグが付けられます。これは、実際に修正されることを最終的に保証するものです。

  2. レガシーc ++ 03モードでは、タイプエイリアスはマクロです。これは大雑把ですが、結果の構文MyPtr<T>は、残りのコード全体でC ++ 11の場合と同じです。

  3. MyPtrこれを設定するには、すべてのauto_ptr変数を見つけて変更する必要があります。


1
これが何を参照しているのかは非常に不明確です(また、言い方をすれば、それはまったく問題ではありません)。
オート

1
@オートファージ私はその答えを信じています...おそらく質問ではないでしょう。
Kain0_0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.