Home > Net >  Automatic template parameter deduction in unique_ptr and make_unique
Automatic template parameter deduction in unique_ptr and make_unique

Time:12-15

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;
}
  • Related