mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
06e2f86bdd
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@231 f6dd340e-d3f9-0310-b409-bdd246841980
51 lines
2.5 KiB
Text
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)).
|