In what situations can a type tt(T) be used as a `stand in' for another type
tt(U)? Since bf(C++) is a strongly typed language the answer is surprisingly
simple: tt(T)s can be used instead of tt(U)s if a tt(T) is accepted as
argument in cases where tt(U)s are requested.

This reasoning is behind the following class which can be used to determine
whether a type tt(T) can be used where a type tt(U) is expected. The
interesting part is that no code is actually generated or executed.  All
decisions are made by the compiler.

In the second part of this section we'll show how the code developed in
the first part can be used to detect whether a class tt(B) is a base class of
another class tt(D) (the tt(is_base_of) template (cf. section ref(TYPETRAITS))
also provides an answer to this question). The code developed here closely
follows the example provided by Alexandrescu hi(Alexandrescu, A.) (2001,
p. 35).

First, a function tt(test) is designed accepting a type tt(U).
The function tt(test) returns a value
of the as yet unknown type tt(Convertible):
        verb(    Convertible test(U const &);)

The function tt(test) is never implemented. It is only declared.  If a type
tt(T) can be used instead of a type tt(U) then tt(T) can also be passed as
argument to the above tt(test) function.

On the other hand, if the alternate type tt(T) cannot be used where a tt(U) is
expected, then the compiler won't be able to use the above tt(test)
function. Instead, it uses an alternative function that has a lower
selection priority but that can em(always) be used with em(any) tt(T) type.

bf(C) (and bf(C++)) offer a very general parameter list, a parameter list that
is always considered acceptable. This parameter list is the familiar
  emi(ellipsis) which represents the em(worst) case the compiler may
encounter.  If everything else fails, then the function defining an ellipsis
as its parameter list is selected.

Usually that's not a productive alternative, but in the current situation it
is em(exactly) what is needed. When confronted with two candidate functions,
one of which defines an ellipsis parameter, the compiler selects the
function defining the ellipsis parameter only if the alternative(s) can't be
used.

Following the above reasoning an alternative function tt(test(...)) is
declared as well. This alternate function does not return a tt(Convertible)
value but a tt(NotConvertible) value:
        verb(    NotConvertible test(...);)

If tt(test)'s argument is of type tt(T) and if tt(T) can be converted to tt(U)
then tt(test)'s return type is tt(Convertible).  Otherwise tt(NotConvertible)
is returned.

This situation clearly shows similarities with the situation encountered in
section ref(CLASSORNOT) where the value tt(isClass) had to be determined
compile time. Here two related problems must be solved:
    itemization(
    it() how do we obtain a tt(T) argument? This is more difficult than might
be expected at first sight as it might not be possible to define a tt(T). If
type tt(T) does not define any constructor then no tt(T) object can be
defined.
    it() how can tt(Convertible) be distinguished from tt(NotConvertible)?
    )
    The first problem is solved by realizing that no tt(T) em(needs) to be
defined. After all, the intent is to decide em(compile-time) whether a type is
convertible and not to define a tt(T) value or object. Defining objects is not
a compile-time but a em(run-time) matter.

    By simply em(declaring) a function returning a tt(T) we can
tell the compiler where it should assume a tt(T):
        verb(    T makeT();)

This mysterious function has the magical power of enticing the compiler
into thinking that a tt(T) object comes out of it. However, this function
needs a small modification before it will actually suit our needs. If, for
whatever reason, tt(T) happens to be an array then the compiler will choke on
tt(T makeT()) as functions cannot return arrays. This, however, is easily
solved, as functions em(can) return em(references) to arrays. So the above
declaration is changed into:
        verb(    T const &makeT();)

Next we pass a tt(T const &) to tt(test):
following code:
        verb(    test(makeT()))

Now that the compiler sees tt(test) being called with a tt(T const &)
argument it decides that its return value is tt(Convertible) if a
conversion is in fact possible. Otherwise it decides that its return value
is tt(NotConvertible) (as the compiler, in that case, selected tt(test(...))).

    The second problem, distinguishing tt(Convertible) from tt(NotConvertible)
is solved exactly the way tt(isClass) could be determined in section
ref(CLASSORNOT), em(viz.) by making their sizes different. Having done so the
following expression determines whether tt(T) is convertible from tt(U) or
not:
        verb(    isConvertible = sizeof(test(makeT())) == sizeof(Convertible);)

By using tt(char) for tt(Convertible) and tt(Char2) (cf. section
ref(CLASSORNOT)) for tt(NotConvertible) the distinction can be made.

    The above can be summarized in a class template tt(LconvertibleToR),
having two template type parameters:
        verbinclude(//CONVERSION examples/conversion.h)
    As the class template deletes its copy constructor no object can be
created. Only its tt(enum) values can be interrogated. The next example writes
tt(1 0 1 0) when run from a tt(main) function:
        verbinclude(//CONVERSION examples/conversion.cc)
