It is worth noting that for the char*
versions of debug_rep
to work correctly, a declaration for debug_rep(const string&)
must be in scope when these functions are defined. If not, the wrong version of debug_rep
will be called:
template <typename T> string debug_rep(const T &t);
template <typename T> string debug_rep(T *p);
// the following declaration must be in scope
// for the definition of debug_rep(char*) to do the right thing
string debug_rep(const string &);
string debug_rep(char *p)
{
// if the declaration for the version that takes a const string& is not in scope
// the return will call debug_rep(const T&) with T instantiated to string
return debug_rep(string(p));
}
Ordinarily, if we use a function that we forgot to declare, our code won’t compile. Not so with functions that overload a template function. If the compiler can instantiate the call from the template, then the missing declaration won’t matter. In this example, if we forget to declare the version of debug_rep
that takes a string
, the compiler will silently instantiate the template version that takes a const T&
.
Declare every function in an overload set before you define any of the functions. That way you don’t have to worry whether the compiler will instantiate a call before it sees the function you intended to call.
Exercise 16.48: Write your own versions of the debug_rep
functions.
Exercise 16.49: Explain what happens in each of the following calls:
template <typename T> void f(T);
template <typename T> void f(const T*);
template <typename T> void g(T);
template <typename T> void g(T*);
int i = 42, *p = &i;
const int ci = 0, *p2 = &ci;
g(42); g(p); g(ci); g(p2);
f(42); f(p); f(ci); f(p2);
Exercise 16.50: Define the functions from the previous exercise so that they print an identifying message. Run the code from that exercise. If the calls behave differently from what you expected, make sure you understand why.