I would expect the last two lines of the first code example to print the same.
The types are deducted as I expect and the the overload resolution is also as I expect.
However, if I explicitly type qualify the function call, then I get a different result then when the type is deduced.
The second code example repeats the exercise replacing overload resolution with specialization. In that case everything works as anyone would expect.
Any explanation?
EDIT: I added one more line showing what Karthik was mentioning regarding print<R,int>(r); which I also do not understand.
Code Example 1: (function template overloading)
#include <iostream>
template <typename T>
void print (T i)
{
std::cout << "simple" << std::endl;
}
template <template<typename> class FF, typename TT>
void print (FF<TT> i)
{
std::cout << "template" << std::endl;
}
template <typename T1, typename T2>
void print (T1 a)
{
T2 b;
std::cout << "two type parameters" << std::endl;
}
template <>
void print<int>(int i)
{
std::cout << "int" << std::endl;
}
template <typename T>
struct R
{
T x;
};
int main()
{
R<int> r;
print<int>(1.1); // ok, prints "int"
print(1.1); // ok, prints "simple"
print<int>(1); // ok, prints "int"
print(1); // ok, prints "int"
print(r); // ok, prints "template"
print<int,int>(1); // ok, prints "two type parameters"
print<R<int>,int>(r); // ok, prints "two type parameters"
print<R<int> >(r); // (1) ?? why "simple" ??
print<R,int >(r); // (2) ?? prints "template", why does it compile at all ??
// gcc 4.6.2 (-std=c++0x) and 4.8.1 (-std=c++11)
// clang++ 3.3.1 same behavior as gcc
}
Code Example 2: (class template specialization).
#include <iostream>
template <typename T>
struct P
{
static void print (T i)
{
std::cout << "simple" << std::endl;
}
};
template <template<class TT> class FF, typename TT>
struct P <FF<TT> >
{
static void print (FF<TT> i)
{
std::cout << "template" << std::endl;
}
};
template <>
struct P<int>
{
static void print(int i)
{
std::cout << "int" << std::endl;
}
};
template <typename T>
struct R
{
T x;
};
int main()
{
R<int> r;
P<double>::print(1.1); // ok, prints "simple"
P<int>::print(1); // ok, prints "int"
P<R<int> >::print(r); // ok, prints "template"
//P<R,int >::print(r); // ok, does not compile
}
Well, let's look at what the compiler thinks of each of these.
template <typename T> void print (T i); // (1)
template <template<typename> class FF, typename TT> void print (FF<TT> i); // (2)
template <typename T1, typename T2> void print (T1 a); // (3)
template <> void print<int>(int i); // (4)
Ok, some preliminaries: we have three function templates here that overload each other (1, 2, and 3), and 4 is a specialization of 1.
All three overloads have a single function parameter. In addition, the functions have template parameters:
1 has a single type template parameter that can be deduced from the function parameter.
2 has a template template parameter and a type template parameter, both of which can be deduced from the function parameter.
3 has two type template parameters, only the first of which can be deduced (making the deduction useless).
Now let's look at the calls. When there are explicit template arguments, the compiler will always "pre-filter" the overloads for those functions that can be instantiated that way.
print<int>(1.1); // ok, prints "int"
One explicit type template argument. 1 matches. 2 doesn't match, because the first argument isn't a template. 3 matches, fixing T1 to int; however, T2 cannot be deduced, so it falls away, too. 1 is chosen with the parameter T being int. This matches the specialization 4.
print(1.1); // ok, prints "simple"
No explicit template arguments. Deduction starts; the argument type is double. 1 matches; T is double. 2 requires the pattern FF<TT>, and double doesn't match that, so failure. 3 can deduce T1 to double, but has nothing for T2, so it fails too. 1 is chosen. The specialization doesn't match.
print<int>(1); // ok, prints "int"
This is identical to the first case, except that during final overload resolution, an implicit conversion happens.
print(1); // ok, prints "int"
This is identical to the second case, except that the deduced type is int (still doesn't match FF<TT>), so the specialization matches.
print(r); // ok, prints "template"
Deduction gives the following results: 1 matches, with T = R<int>. For 2, R<int> matches the pattern FF<TT>, so it is viable, with FF = R and TT = int. 3, as usual, doesn't know what to do with T2. Overload resolution gets identical sequences for 1 and 2 (identity), so partial function template ordering resolves the ambiguity: 2 is more specialized than 1 and is chosen.
print<int,int>(1); // ok, prints "two type parameters"
Two explicit type template arguments. 1 only accepts one. 2 wants a template as the first argument. 3 is left.
print<R<int>,int>(r); // ok, prints "two type parameters"
This is identical to the previous case. The first argument is R<int> instead of int, but that's still just a type and 2 doesn't like it.
print<R<int> >(r); // (1) ?? why "simple" ??
This is identical to the first and third cases. We have one explicit type template argument. 3 fails to deduce T2, 2 wants a template as the first argument, so 1 is the only choice. R<int> is a type, not a template.
print<R,int >(r); // (2) ?? prints "template",
Here, we have two explicit template arguments, the first a template, the second a type. 1 only accepts one argument. 3 wants a type for its first template parameter. 2 is happy to take the template for its first and the type for its second parameter.
The key lessons here are:
Explicit template arguments are matched to the template parameters before any deduction or overload resolution happens, so only some functions match in the first place.
1 and 2 are overloads, and overload resolution happens separately for them. It would be different if 2 was a specialization of 1, but partial function template specialization doesn't exist.
It's only a template until you give it arguments. An instantiated function template is a function. An instantiated class template is a class (and thus a type). There is no difference between the instantiation of a class template and a non-template class, except for the pattern matching that argument deduction and partial specialization do.
Edit: To answer the expanded question.
When I replace function overloading with template specialization, then template pattern matching works as I would have expected. I have some trouble believing that the pattern matching rules also differ between classes and functions.
This is a matter of perspective. There are no pattern matching rules for classes and functions, so you can't say that they differ or not. There are pattern matching rules for partial specialization and for template argument deduction. These are actually the same; the section on partial specialization (14.5.5) refers to the section on function template argument deduction (14.8.2).
So the pattern matching rules are the same.
However, argument deduction only applies to functions (there's no argument deduction for class templates, at least not yet), while partial specialization only applies to classes (you can't partially specialize functions). This is the key difference between functions and classses: in your first example, you have two function templates:
template <typename T> void print(T i);
template <template <typename> class FF, typename TT> void print(FF<TT> i);
These are two different templates. They are completely independent. It's up to the complicated rules and interactions of explicit parameter passing, argument deduction, and overload resolution to determine which one is meant in any given invocation. However, and this is important, each can exist without the other. In other words, imagine you had only one function:
template <template <typename> class FF, typename TT> void something_else(FF<TT> i);
Would you then be surprised that something_else<R, int>(r); is valid? You have a template with two parameters, and you pass two arguments. The existence of another template with just one argument doesn't change that!
This is important, so I'll repeat it: Two function templates, even if they have the same name, are completely independent templates.
Not so with classes. If you try the same thing with classes, the compiler will complain:
template <typename T> class Q {};
template <template <typename> class FF, typename TT> class Q {};
Clang says:
redef.cc:2:5: error: too many template parameters in template redeclaration
You cannot have two class templates with the same name. The compiler thinks you want to declare the old Q again, and complains that the template parameter lists don't match.
The only thing you can do with class templates is specialize them, as you did in your second example:
template <typename T> class P {};
template <template <typename> class FF, typename TT> class P<FF<TT>> {};
But note that these are not independent templates. They are not even the same thing. The first is a class template, whereas the second is a class template partial specialization. The second is completely dependent on the first; removing the primary template means the specialization no longer compiles:
redef.cc:2:64: error: explicit specialization of non-template class 'P'
Unlike the overloaded function templates, a class template partial specialization is not an entity the user can reference. For the user, there is one template, P, and it has one template parameter. The specialization will match if this one parameter takes a specific form, but unlike the second function template in the first example, the specialization is not an independent template with two parameters.
This is why P<R<int>>::print(r) compiles and works: P has one parameter, and R<int> is passed for it. The partial specialization matches the pattern and is therefore chosen. But P<R, int>::print(r) does not work: P only has one template parameter, and here you're trying to pass two. The specialization is not its own entity and therefore is not considered.
But the function templates are all independent, full templates. Only the full specialization template <> void print<int>(int i) is not.
So to sum up:
Function templates can be fully specialized or overloaded. Overloaded function templates are fully independent: when you want to know what arguments you can or should explicitly supply, look at all their parameter lists in turn.
Avoid specializing function templates. It interacts with overloaded function templates in weird ways, and you can end up with a function different from what you expected being called. Just overload function templates, with other function templates and plain functions. The partial ordering rules are intuitive; just remember that when in doubt, a plain function is chosen over a template.
Class templates can be fully or partially specialized, but not overloaded. Specializations are not independent templates; when instantiating a class template, you always have to go to the primary template for the parameter list.
The matching rules for choosing a partial specialization and for deducing template arguments from function arguments are the same; however, when you explicitly pass template arguments to a function template, deduction is not performed for these parameters.
This is a guess not an answer, those with the standard at their finger tips can enlighten us all,
But let me take an educated guess
template <template<typename> class FF, typename TT> //......(1)
TT is a type while FF is considered a template template parameter
template <typename T> // .....(2)
T is a type
Now when Explicitly specifying the type, R<int>, it is a concrete type, thus (2) is picked.
When asking it to infer, I guess the compiler tries both options and (1) fits closer (or more specific), and thus that is chosen.
When explicitly specifying <R,int>, ofcourse we use the exact signature of (1) and that is why that one is picked.
+1 to the question, I would not have expected this either.
Perhaps some useful information can be found here
The line print< R<int> >(r); looks like a single-template-parameter print (it can't guess what you want) so it calls the single-template-parameter function with T = R<int>.
print< R,int >(r); calls for a two-template-parameter function, of which there is only one version (template). Luckily R is a template that can be instantiated with int so it compiles.
It would print simple because the type R<int> is deduced as int. In your case, you need to pass 2 parameters to explicitley make it deduce as template <template<typename> class FF, typename TT>
Related
When I run the program below, I get an error saying that more than one specialization matches the template argument list of class X<int, int*, 10>. The compiler obviously can't decide whether to use "Specialization 1" or "Specialization 2". I don't understand why that is the case because I thought that the compiler determines the level of specialization based on the number of template parameters. So, since "Specialization 1" has 2 template parameters (template<class T, int I>), and "Specialization 2" has only 1 template parameter (template<class T>) I figured that "Specialization 2" is more specialized than "Specialization 1". Obviously my reasoning is incorrect, so could someone explain the logic behind deducing which template is more specialized?
#include <iostream>
using namespace std;
template<class T, class U, int I> struct X {
void f() { cout << "General Template" << endl; }
};
template<class T, int I> struct X<T, T*, I> {
void f() { cout << "Specialization 1" << endl; }
};
template<class T> struct X<int, T*, 10> {
void f() { cout << "Specialization 2" << endl; }
};
int main() {
X<int, int*, 10> f;
f.f();
return 0;
}
This topic is unfortunately very complicated! I'm basing myself on this answer and cppreference, while quoting from the current working draft of the standard.
Firstly, according to "Matching of partial specializations":
A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list, and the deduced template arguments satisfy the associated constraints of the partial specialization, if any.
In your example, the context is the statement X<int, int*, 10> f;, which matches both partial specializations:
template<class T, int I> struct X<T, T*, I> {...} // -> T = int, I = 10
template<class T> struct X<int, T*, 10> {...} // -> T = int
Since this is the case, further checking is required to determine whether one of these candidates is more specialized than the other. That is described under "Partial ordering of partial specializations":
For two partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second according to the ordering rules for function templates:
Each of the two function templates has the same template parameters and associated constraints as the corresponding partial specialization.
Each function template has a single function parameter whose type is a class template specialization where the template arguments are the corresponding template parameters from the function template for each template argument in the template-argument-list of the simple-template-id of the partial specialization.
That is very wordy, but as shown by the example it simply comes down to writing the partial specializations as function arguments:
template<class T, int I> void f(X<T, T*, I>); // #1
template<class T> void f(X<int, T*, 10>); // #2
From there we have to look at a different section about the "Partial ordering of function templates". Quoting the relevant paragraphs:
Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. [...]
To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.
Using the transformed function template's function type, perform type deduction against the other template as described in [temp.deduct.partial].
In other words, transform #1 and #2 (again) by "instantiating" each with unique arguments, that is, different from any other arguments present:
void f(X<Ut1, Ut1*, Uv1>); // #A
void f(X<int, Ut2*, 10>); // #B
And then use their "function type", being the return type and the argument types, to perform deduction according to yet another section, "Deducing template arguments during partial ordering":
The deduction process uses the transformed type as the argument template and the original type of the other template as the parameter template.
This process is done twice for each type involved in the partial ordering comparison: once using the transformed template-1 as the argument template and template-2 as the parameter template and again using the transformed template-2 as the argument template and template-1 as the parameter template.
Ok, going by the example on cppreference:
// #1 from #B:
// void(X<T, T*, I>) from void(X<int, Ut2*, 10>): deduction fails
// #2 from #A:
// void(X<int, T*, 10>) from void(X<Ut1, Ut1*, Uv1>): deduction fails
At least, I think that's the case, and therefore the result of this whole ordeal would be that neither template is more specialized than the other.
Sorry for the lack of a better title.
While trying to implement my own version of std::move and understanding how easy it was, I'm still confused by how C++ treats partial template specializations. I know how they work, but there's a sort of rule that I found weird and I would like to know the reasoning behind it.
template <typename T>
struct BaseType {
using Type = T;
};
template <typename T>
struct BaseType<T *> {
using Type = T;
};
template <typename T>
struct BaseType<T &> {
using Type = T;
};
using int_ptr = int *;
using int_ref = int &;
// A and B are now both of type int
BaseType<int_ptr>::Type A = 5;
BaseType<int_ref>::Type B = 5;
If there wasn't no partial specializations of RemoveReference, T would always be T: if I gave a int & it would still be a int & throughout the whole template.
However, the partial specialized templates seem to collapse references and pointers: if I gave a int & or a int * and if those types match with the ones from the specialized template, T would just be int.
This feature is extremely awesome and useful, however I'm curious and I would like to know the official reasoning / rules behind this not so obvious quirk.
If your template pattern matches T& to int&, then T& is int&, which implies T is int.
The type T in the specialization only related to the T in the primary template by the fact it was used to pattern match the first argument.
It may confuse you less to replace T with X or U in the specializations. Reusing variable names can be confusing.
template <typename T>
struct RemoveReference {
using Type = T;
};
template <typename X>
struct RemoveReference<X &> {
using Type = X;
};
and X& matches T. If X& is T, and T ia int&, then X is int.
Why does the standard say this?
Suppose we look af a different template specialization:
template<class T>
struct Bob;
template<class E, class A>
struct Bob<std::vector<E,A>>{
// what should E and A be here?
};
Partial specializations act a lot like function templates: so much so, in fact, that overloading function templates is often mistaken for partial specialization of them (which is not allowed). Given
template<class T>
void value_assign(T *t) { *t=T(); }
then obviously T must be the version of the argument type without the (outermost) pointer status, because we need that type to compute the value to assign through the pointer. We of course don't typically write value_assign<int>(&i); to call a function of this type, because the arguments can be deduced.
In this case:
template<class T,class U>
void accept_pair(std::pair<T,U>);
note that the number of template parameters is greater than the number of types "supplied" as input (that is, than the number of parameter types used for deduction): complicated types can provide "more than one type's worth" of information.
All of this looks very different from class templates, where the types must be given explicitly (only sometimes true as of C++17) and they are used verbatim in the template (as you said).
But consider the partial specializations again:
template<class>
struct A; // undefined
template<class T>
struct A<T*> { /* ... */ }; // #1
template<class T,class U>
struct A<std::pair<T,U>> { /* ... */ }; // #2
These are completely isomorphic to the (unrelated) function templates value_assign and accept_pair respectively. We do have to write, for example, A<int*> to use #1; but this is simply analogous to calling value_assign(&i): in particular, the template arguments are still deduced, only this time from the explicitly-specified type int* rather than from the type of the expression &i. (Because even supplying explicit template arguments requires deduction, a partial specialization must support deducing its template arguments.)
#2 again illustrates the idea that the number of types is not conserved in this process: this should help break the false impression that "the template parameter" should continue to refer to "the type supplied". As such, partial specializations do not merely claim a (generally unbounded) set of template arguments: they interpret them.
Yet another similarity: the choice among multiple partial specializations of the same class template is exactly the same as that for discarding less-specific function templates when they are overloaded. (However, since overload resolution does not occur in the partial specialization case, this process must get rid of all but one candidate there.)
Consider the following code:
template <typename T>
struct dependent_type
{
using type = T;
};
template <typename T>
auto foo(T) -> std::enable_if_t<std::is_same<T, int>{}>
{
std::cout << "a\n";
}
template<typename T>
void foo(typename dependent_type<T>::type)
{
std::cout << "b\n";
}
The first overload of foo can deduce T from its invocation.
The second overload of foo is a non-deduced context.
int main()
{
foo<int>( 1 ); // prints "b"
foo<double>( 1.0 ); // prints "b"
foo( 1 ); // prints "a"
}
Why does foo<int>( 1 ) print "b" and not "a"?
wandbox example
Essentially the partial ordering rules say that the dependent_type overload is more specialized because of that non-deduced context.
The process for ordering template functions is based on transforming the template function types and performing template deduction on each in turn, once going from the first template (the one taking T) to the second (the one taking dependent_type), then from the second to the first.
The rules are far too complex to replicate here, but go read [temp.func.order] and the passages it links to if you want the gory details. Here's a quick simplification:
For each template parameter of the template function, make up a unique type and replace the parameter with that. The transformed types for this example are:
void foo(UniqueType); //ignoring the SFINAE for simplicity
void foo(typename dependent_type<UniqueType>::type);
We then perform template deduction in two directions: once using the parameters of the first template as arguments to the second, and once using the parameters of the second as arguments to the first. This is akin to performing deduction on these function calls:
//performed against template <class T> void foo(typename dependent_type<T>::type);
foo(UniqueType{});
//performed against template <class T> void foo(T);
foo(dependent_type<UniqueType>::type{});
In carrying out these deductions, we're trying to discern whether one overload is more specialized then the other. When we try the first one, deduction fails, since typename dependent_type<T>::type is a non-deduced context. For the second one, deduction succeeds because dependent_type<UniqueType>::type is just UniqueType, so T is deduced to UniqueType.
Since deduction failed going from the second template to the first, the second template is taken as being more specialized than the first. The final result is that the overload resolution prefers the second template for foo<int>(1).
Consider this example (also available on wandbox):
template <template <auto> class>
void test() { }
template <int>
struct X { };
Trying to instantiate test<X>() on clang++ 4.0 (trunk) results in a compilation error:
error: no matching function for call to 'test'
test<X>();
^~~~~~~
note: candidate template ignored:
invalid explicitly-specified argument for 1st template parameter
void test() { }
My initial assumption/intuition was that test could be used to match any template having a non-type parameter.
However, the following code snippet successfully compiles:
template <template <auto> class>
void test() { }
// vvvv
template <auto>
struct X { };
Is this intended? Could not find anything conclusive in P0127R2.
It's definitely intended. Template-template parameters can only match templates which take the same kinds of arguments. This:
template <template <auto> class>
void test() { }
can only be instantiated with a class template that can take any kind of non-type parameter. But this:
template <int>
struct X { };
is not such a class template. X can only be instantiated with an int. It simply does not match the specification for the template template parameter, hence the error. What if test wanted to instantiate its class template with a pointer type? Or pointer to function or pointer to member? That would be impossible.
Your second attempt, with template <auto> struct X { }; does match the template-template parameter, hence is well-formed. Note also that the reverse, having test take a template <int> class parameter and passing in template <auto> struct X { }; is also well-formed as the argument is more general than the parameter.
The relevant wording is in [temp.arg.template]:
A template-argument matches a template template-parameter P when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template A matches
the corresponding template parameter in the template-parameter-list of P. Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are
equivalent (14.5.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively.
Note: the equivalence wording accepts the auto - auto case and rejects the auto - int case, but also seems to reject the int - auto case (based on my reading). I'm going to try to get some clarification on it.
In addition to Barry's answer, which made me curious, here are the four possible combinations and results using Clang 4.0 (SVN), see also on wandbox:
template <bool> struct obj_bool { }; // object taking a value of boolean type
template <auto> struct obj_auto { }; // object taking a value of deduced type
// ^^^^^^ Note: this is a template value argument (non-type template argument)
template <template <auto> typename> void fn_auto() { }
template <template <bool> typename> void fn_bool() { }
// ^^^^^^^^^^^^^^^^^^^^^^^^ Note: this is a template type argument
// ^^^^^^ taking a template value argument
int main() {
fn_bool<obj_bool>(); // #1 bool->bool OK (exact match)
fn_auto<obj_auto>(); // #2 auto->auto OK (exact match)
fn_bool<obj_auto>(); // #3 bool->auto OK (sub-set)
//fn_auto<obj_bool>(); // #4 auto->bool Error: no matching function.
}
From that, #1 and #2 are obviously exact matches and are working as expected. #3 would invoke the bool implementation on a template that can handle not only bool but all types, whereas #4 would try to invoke a definition expecting a generalized object (auto) with an object providing only a sub-set (bool) of possibilities.
The templated function fn_auto promises possible instantiations for templates taking any value type (auto). Thus giving it only a sub-set of possibilities (bool) violates this promise.
Though not immediately obvious, the restriction makes sense. And sorry for my wording not being C++ Standard compliant.
The following code prints "func 2".
Why does the compiler treat the second template as a better match, in presence of explicit (not deduced) template arguments? Why is there no ambiguity?
I'd appreciate quotations from the C++ standard.
#include <iostream>
template<class T>
struct identity
{
typedef T type;
};
template<class T>
void func(T)
{
std::cout << "func 1\n";
}
template<class T>
void func(typename identity<T>::type)
{
std::cout << "func 2\n";
}
int main()
{
func<int>(1);
}
Both candidates are viable and take identical arguments, so the overload resolution process falls back to the last tiebreaker: partial ordering of function templates [temp.func.order].
The rule is that we synthesize a new type for each template type parameter and attempt to perform deduction on each other overload. For 1, we synthesize a type Unique1, which fails deduction on 2 because T is a non-deduced context. For 2, we synthesize a type Unique2, which succeeds deducing T = typename identity<Unique2>::type. Since deduction succeeds in one direction and not the other, that makes 2 more specialized than 1, hence it's preferred.
Note that template partial ordering rules are somewhat incomplete in the standard. If you simply add another argument of type T, the preference flips.