массивы — Как я могу сделать правильный шаблон псевдоним C ++ для std :: unique_ptr

Я хочу сделать шаблон псевдонима для std::unique_ptr которая обеспечивает мою собственную функцию удаления.

unique_ptr имеет скалярную и массивную реализацию, они определены так:

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, Легко сделать псевдоним только для одной версии, например так:

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?

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,

Конечно, это все довольно бессмысленно, но я полагаю, ваш реальный 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>;

— РЕДАКТИРОВАТЬ —

ОП говорят

Я отредактировал вопрос, чтобы включить пример реализации ArrayDeleter

Не уверен (я делаю много ошибок со специализацией массива шаблонов), но я полагаю, это должно работать, если вы можете изменить ArrayDeleter следующее

template <typename>
struct ArrayDeleter;

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector