Why do I get automatic template parameter deduction if I call class constructor directly but I do not get it in std::unique_ptr
and std::make_unique
? Here is an example:
#include <memory>
template <class T>
class C
{
public:
C(const T * const t_) : t(t_) {}
~C(void) { delete t; }
private:
const T * const t;
};
Example 1 (works):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
return 0;
}
Example 2 (does not compile):
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
std::unique_ptr p(c); // class template argument deduction failed
return 0;
}
Example 3 (works):
int main(void)
{
const int * const t = new int;
const auto c = std::make_unique<C<int>>(t);
return 0;
}
Example 4 (does not compile):
int main(void)
{
const int * const t = new int;
// no matching function for call to ‘make_unique<template<class T> class C>(const int* const&)
const auto c = std::make_unique<C>(t);
return 0;
}
The code was compiled with g -std=c 17
(gcc-11.2.0).
What is the problem in examples 2 and 4? How can one fix them?
Thank you very much for your help!
CodePudding user response:
In #2, CTAD is deliberately disabled for std::unique_ptr
to avoid the issues with std::unique_ptr(new T[10])
, which looks just like std::unique_ptr(new T)
but needs delete[]
instead of delete
.
In #4, the language simply doesn’t support this: there’s no way to pass any class template as a template argument so as to do CTAD based on the function arguments inside std::make_unique
. (One could pass a class template with a specific (meta)signature, but that wouldn’t be appropriate for a general facility.)
CodePudding user response:
This is one way to solve it:
template <class T>
auto MakeUnique(T t)
{ return std::unique_ptr<std::remove_reference_t<decltype(*t)>>(t); }
int main(void)
{
const int * const t = new int;
auto * const c = new C(t);
auto p = MakeUnique(c);
return 0;
}