I want to make an alias template for std::unique_ptr
that supplies my own deleter function.
unique_ptr
has both a scalar and an array implementation, they're defined like this:
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 running into trouble trying to override both the scalar and array versions of unique_ptr
. It's easy to make an alias for just one version, like this:
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, like this:
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 can I create a single aliased name that works for both the array and scalar versions of unique_ptr
?
You appear to be trying to specialize a using
declaration. You may not.
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;
Now this has disadvantages in that it blocks deduction rather completely.
We can fix this by moving the specialization elsewhere.
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
now:
template<class T>
using my_unique_ptr = std::unique_ptr<T, Deleter<T>>;
is simpler, and may permit more deduction of T
.
Of course, this is all pretty pointless, but I presume your real Deleter
isn't the same as std::default_delete
.
You should show us your ArrayDeleter
but... are you sure that you can't solve your problem with a unique using
and std::conditional
?
I mean, something like
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 ---
The OP say
I've edited the question to include an example ArrayDeleter implementation
Not sure (I do a lot of errors with template array specializations) but I suppose that should work if you can modify ArrayDeleter
as follows
template <typename>
struct ArrayDeleter;
template <typename T>
struct ArrayDeleter<T[]>
{ void operator()(T* ptr) { delete [] ptr; } };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With