Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ When template argument deduction fails

Why can't C++ determine that I intend to create a unique_ptr<A> with this syntax? (a has previously been declared as unique_ptr<A>)

a = unique_ptr(new A());

It seems awfully redundant to have to include <A>. This works for most functions templates I use, why not unique_ptr?

EDIT: C++ now supports make_unique, with no redundancy.

like image 221
Jeff Linahan Avatar asked Apr 03 '11 07:04

Jeff Linahan


People also ask

What is template argument deduction?

Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.

Can there be more than one argument to template?

Yes, like normal parameters, we can pass more than one data type as arguments to templates.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

CAN default arguments be used with the template?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };


1 Answers

std::unique_ptr is a class template, not a function template. Argument deduction only happens for function templates, not class templates.

A commonly used trick is to write a function template that creates an object of the instantiated class template type, for example:

template <typename T>
std::unique_ptr<T> make_unique_ptr(T* ptr) 
{
    return std::unique_ptr<T>(ptr);
}

For std::unique_ptr, though, I'd avoid doing this: a std::unique_ptr object should directly take ownership of the dynamically allocated object, so there should not be a need for this. Your code should either be written as:

std::unique_ptr<A> a(new A());

or, if a already exists, a call to reset() can be used:

a.reset(new A());

As for why type deduction won't work for instantiating a class template, consider the following example:

template <typename T>
struct X
{
    template <typename U> X(U) { }
};

There is no way that T could be deduced from an invocation of the constructor. Even in "simpler" cases where there is a constructor with a parameter of type T, there can still be trouble since constructors can be overloaded.

like image 141
James McNellis Avatar answered Sep 22 '22 22:09

James McNellis