Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Template Formal Ordering Rules

Tags:

c++

templates

I'm having difficulty understanding the how formal ordering rules work as described in chapter 12 of the book C++ Templates, The Complete Guide by D. Vandevoorde and N. M. Josuttis. On page 188 of this book the authors give the following scenario used to decide which of two viable function templates is more specialized:

From these two templates we synthesize two lists of argument types by replacing the template parameters as described earlier: (A1) and (A2*) (where A1 and A2 are unique made up types). Clearly, deduction of the first template against the second list of argument types succeeds by substituting A2* for T. However, there is no way to make T* of the second template match the nonpointer type A1 in the first list. Hence, we formally conclude that the second template is more specialized than the first.

I'd like some understanding this example.

Edit

I believe that the two function templates referred to in the above quote are

template<typename T>
int f(T)
{
    return 1;
}

template<typename T>
int f(T*)
{
    return 2;
}
like image 989
Olumide Avatar asked May 11 '26 12:05

Olumide


1 Answers

The rules are a bit harder to explain than to use. The idea is that a template is more specialized than another template if the set of possible instantiations of the more specialized is a strict subset of the set of possible instantiations of the less specialized one.

That is, every type that can be use as an argument to the more specialized can also be used as argument to the less specialized, and there is at least one type that can be used with the less specialized that cannot be used with the more specialized.

Given the two templates:

template <typename A> void f( A );   // [1]
template <typename B> void f( B* );  // [2]

The question to resolve is which one of them is more generic (i.e. can take a greater number of arguments). The whole description in the standard is done in terms of synthetic unique types that are used for A and B, but in a less precise way we can try to resolve by hand waving.

Say we find a type X that matches the second template argument, then an instantiation of that second template will look like void f( X* ) (besides the fact that it is a template). Now, can the template [1] be used to generate an equivalent function? Yes, by making A == X* in the type deduction. Can we do it in the opposite direction? Say we find a type Y with which we can instantiate the first template, we get void f( Y ). Can the second template match this call? No, only for the subset of types that are pointers the previous statement can hold.

That means that the second template is more specialized, since for every valid instantiation of the second template, we can also instantiate the first template, but there are some instantiations of the first template that would not be valid instantiations of the second.

For a practical example, f( char* ) can be matched by both templates, but f( 5 ) can only be matched by the first one. The reason for the weird explanation in terms of synthetic types is that a single example does not guarantee the order, it has to hold for all types. The synthetic type is a representative of any type.

like image 200
David Rodríguez - dribeas Avatar answered May 14 '26 03:05

David Rodríguez - dribeas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!