cppannotations/yo/functiontemplates/sfinae.yo
Frank B. Brokken 06e2f86bdd Preparing 8.0.0
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@231 f6dd340e-d3f9-0310-b409-bdd246841980
2009-07-15 11:58:17 +00:00

51 lines
2.5 KiB
Text

Consider the following struct definition:
verb(
struct Int
{
typedef int type;
};
)
Although at this point it may seem strange to embed a typedef in a struct,
as we'll see in chapter ref(ADVANCEDTEMPL) there are certainly situations
where this is actually very useful as it defines a standard interface to some
core type defined in various template types. It allows us to define a variable
of a kind that is required by the template. E.g., (the tt(typename) in the
following function parameter list can be ignored for now. It's a subtlety that
is explained in detail in section ref(DISTINGUISH)):
verb(
template <typename Type>
void func(typename Type::type value)
{
}
)
To call tt(func(10)) tt(Int) has to be specified explicitly since there
may be many structs that define tt(type): the compiler needs some
assistance. The correct call is tt(func<Int>(10)). Now it's clear that tt(Int)
is meant and the compiler correctly deduces that tt(value) is an tt(int).
But templates may be overloaded, and our next definition is:
verb(
template < typename Type >
void func(Type value)
{}
)
Now, to make sure this function is used we specify tt(func<int>(10)) and
again this compiles flawlessly.
But as we've seen earlier in this chapter when the compiler determines
which template to instantiate it creates a list of viable functions by
matching the available function prototypes with the provided actual
type. Therefore it has to determine the types of the parameters and herein
lies a problem. When evaluating tt(Type = int) the compiler will encounter the
prototypes tt(func(int::Type)) (first template definition) and tt(func(int))
(second template definition). But there is no tt(int::Type), and so in a sense
this generates an error. However, the error results from substituting the
provided template type argument into the various template definitions. An
type-problem caused by substituting a type in a template definition is em(not)
considered an error, but a mere indication that that particular type cannot be
substituted in that particular template which is therefore removed from the
list of candidate functions. This principle is known as em(substitution
failure is not an error) (i(SFINAE)) and it is used often by the compiler to
select not only a simple overloaded function (as shown here) but also to make
the correct choice when selecting the appropriate specialization (see also
chapters ref(TEMPCLASS) and ref(ADVANCEDTEMPL)).