Function template overload: const * vs. const &

When I have two template functions, such as:

template<class T> void foo( T const& ) { // do something with a const reference cout << "const reference version"; } template<class T> void foo( T const* ) { // do something with a const pointer cout << "const pointer version"; } 

Why does the compiler select the first version when creating an instance using a non-constant pointer type?

 int* bar; foo( bar ); // prints "const reference version" char const* baz; foo( baz ); // prints "const pointer version" 
+7
source share
4 answers

The reason is that bar is a non-constant pointer, so int* const& actually matches int const* better, because it does not need to add const to the type of the pointer.

If bar were const qualified, then this would be an exact match for version T const* .

+4
source
 #include <iostream> using namespace std; void foo(int const&) { cout << "const reference" << endl; } void foo(int const*) { cout << "const pointer" << endl; } int main() { int *hi; foo (hi); //const pointer foo((*hi)); //const reference foo(&(*hi));//const pointer } 

The deal here is links, and the pointers are different. A pointer is a unique type where, as a reference to a value, it is no different from the value itself or, rather, an alias of the object. So, for example, this version of the above code will not compile.

 #include <iostream> using namespace std; void foo(int const&) { cout << "const reference" << endl; } void foo(int) { cout << "hi there" << endl; } int main() { int hi; foo(hi); //const reference } 

Since the declarations of foo are mixed. The compiler cannot decide between them.

+2
source

You can determine what happens to your template types using typeid .

 #include <iostream> #include <typeinfo> using namespace std; template<class T> void foo( T const& ) { cout << "const reference version T="<< typeid(T).name()<<endl; } template<class T> void foo( T const* ) { cout << "const pointer version T="<<typeid(T).name()<<endl; } int main() { int* i_ptr=0; foo(i_ptr); const int* ci_ptr=0; foo(ci_ptr); } 

These outputs (note the exact output will depend on your compiler)

 const reference version T=Pi const pointer version T=i 

Which shows that in the first case T = int* and the full argument type int* const& , and in the second T=int and the full argument type int const * .

+1
source

template<class T> void foo( T const* ) requires a const pointer to T Well, if that was the only declaration you had, there would be a compilation error, since you are trying to pass a non const pointer as an argument.

With template<class T> void foo( T const& ) deduced type of T is int* , which is specified by a function reference.

0
source

All Articles