2017-03-02 4 views
4

私自身のdeleter関数を提供するstd::unique_ptrのエイリアステンプレートを作りたいと思います。私はunique_ptrのスカラと配列の両方のバージョンを上書きしようとしてトラブルに実行しているよstd :: unique_ptrの有効なC++エイリアステンプレートを作るには

template <class T, class D = default_delete<T>> 
class unique_ptr // scalar 

template <class T, class D> 
class unique_ptr<T[], D> // array 

unique_ptrはスカラと配列の実装の両方を持っている、彼らはこのように定義されています。それはこのように、1つのバージョンだけのエイリアスを作るのは簡単です:

template<class T> 
struct Deleter { 
    void operator()(T* ptr) { delete ptr; } 
}; 

template<class T> 
using my_unique_ptr = std::unique_ptr<T Deleter<T>>; 

をしかし、私はこのように、第二のエイリアスを追加しようとすると:

template<class T> 
struct ArrayDeleter { 
    void operator()(T* ptr) { delete [] ptr; } 
}; 
template<class T> 
using my_unique_ptr = std::unique_ptr<T[], ArrayDeleter<T>>; 

...私は、コンパイルエラーになってしまいます"my_unique_ptr"はあいまいです。

私の質問はunique_ptrの配列バージョンとスカラーバージョンの両方で動作する別名を1つ作成するにはどうすればよいですか?

答えて

4

using宣言を特化しようとしているようです。できません。

template<class T> 
struct my_unique_ptr_helper { 
    using type = std::unique_ptr<T, Deleter<T>>; 
}; 
template<class T> 
struct my_unique_ptr_helper<T[]> { 
    using type = std::unique_ptr<T[], ArrayDeleter<T>>; 
}; 

template<class T> 
using my_unique_ptr = typename my_unique_ptr_helper<T>::type; 

ここでは、これは控除を完全にブロックするという欠点があります。

専門分野を他の場所に移動することでこれを解決できます。今

template<class T> 
struct Deleter { 
    void operator()(T* ptr) const { 
    delete ptr; 
    } 
}; 
template<class T> 
struct ArrayDeleter { 
    void operator()(T* ptr) const { 
    delete[] ptr; 
    } 
}; 
template<class T> 
struct Deleter<T[]>:ArrayDeleter<T> {}; // inheritance 

template<class T> 
using my_unique_ptr = std::unique_ptr<T, Deleter<T>>; 

は単純であり、かつTのより多くの控除を許可することができます。

もちろん、これはまったく意味がありませんが、実際のDeleterstd::default_deleteと同じではありません。

+0

を次のようにArrayDeleterを変更することができればそれが動作するはずの感謝を想定してください。 ArrayDeleter構造体を作成する必要はありませんでした。代わりに、私は一般的な "template Deleter"をT []のDeleter専門と一緒に作成しました。 –

2

ArrayDeleterを表示する必要がありますが、ユニークなusingstd::conditionalで問題を解決できないことは確かですか?

私が意味する、

template <typename T> 
using my_unique_ptr = std::unique_ptr<T, 
     typename std::conditional<std::is_array<T>::value, 
            ArrayDeleter<T>, 
            Deleter<T>>::type>; 

のようなもの--- EDIT ---

OPは私が実装ArrayDeleter例を含めるように質問を編集した

言います

ない(私はテンプレートアレイ専門とエラーの多くを行う)が、私は、これは私のために働いた

template <typename> 
struct ArrayDeleter; 

template <typename T> 
struct ArrayDeleter<T[]> 
{ void operator()(T* ptr) { delete [] ptr; } }; 
+0

サンプルのArrayDeleter実装を含めるように質問を編集しました。 –

+0

@DominicDosSantos - 回答が改善されました。お役に立てれば – max66

関連する問題