How can I create a valid C ++ alias pattern for std :: unique_ptr

I want to create an alias template for std::unique_ptrthat supplies my own deleter function.

unique_ptr has both a scalar and an array implementation, they are defined as follows:

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

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

I'm having trouble trying to override both scalar and massive versions unique_ptr. It is easy to make an alias for only one version, for example:

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

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

But when I try to add a second alias, for example:

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

... I end up with compiler errors because " my_unique_ptr" is ambiguous.

My question is: How do I create one alias that works for both an array and scalar versions unique_ptr?

+4
2

, 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.

, , , Deleter std::default_delete.

+4

ArrayDeleter, ... , using std::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

( ), , , ArrayDeleter

template <typename>
struct ArrayDeleter;

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

Source: https://habr.com/ru/post/1671299/


All Articles