Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template argument deduction and pointers to constants

Tags:

c++

templates

I had defined two overloaded functions, their declarations are as follows

template <class T> void Foo(const T *p);    // lets call this Foo_p

template <class T> void Foo(const T& r);    // lets call this Foo_r

When I call

Foo( ptr_to_non_const );

Foo_r gets called. I assumed that constant qualification are stripped away from pointers when looking for best match. Since T* is more specialized than T& I expected that Foo_p will be called.

Could anyone point me to a good resource that lists template argument deduction rules and the precedence of matches.

In this particular case I intend template <class T> void Foo(const T& r) to be called for non-pointer type. Does it mean I have to define the functions with and without const qualifications. For one argument it is not a big deal, but my function take more than one pointer, so I would want to avoid the repition. Any suggestions would be appreciated.

like image 244
san Avatar asked Dec 13 '25 10:12

san


1 Answers

The template deduction rules are quite complicated and I'm not sure if there is anywhere a simple summary. However, if two templates are candidates and one of them requires a conversion while the other does not, the one not requiring a conversion to produce the template argument is chosen. In your example, the matching instantiations are thus:

S* ptr_to_non_const = ...;
Foo(ptr_to_non_const); // => candidates:
                       //   a. F(const T&) with `T` deduced as `S*` requires no
                       //      conversion
                       //   b. F(const T*) with `T` deduced as `S` requires `S*` to
                       //      `S const*` conversion

To force the use of the pointer overload, you can remove the reference version from the overload set using std::enable_if<...> together with std::is_pointer<...>:

template <class T>
typename std::enable_if<!std::is_pointer<T>::value>::type
Foo(const T& r);

Although this uses the C++ 2011 features, both std::enable_if<...> and std::is_pointer<...> can be implemented quite easy with a C++ 2003 compiler, as well (and I'm pretty sure that Boost has done so).

like image 90
Dietmar Kühl Avatar answered Dec 16 '25 00:12

Dietmar Kühl