Saeed Amrollahi said:
C++ allow to declare templates with various kind of template
parameters.
I wonder what are the applications of these two template parameters:
1. template<class> // no identifier for template parameter
class C1 {
};
How it differs from this one:
template<class T>
class C2 {
};
C1<int> c1;
C2<int> c2;
As given there is essentially no difference since, with the
definition of both C1 and C2, you make no use of the template
parameter type. Note: it would be /possible/ to do so in the case of
C2, but not for C1 since the parameter is not named.
This is really no different than what you find in the case of ordinary
function calls that use unnamed function call parameters:
#include <iostream>
void f(int) // unnamed function call parameter - int
{
std::cout << "Calling void f(int)...\n";
}
void f(char c) // named function call parameter - char
{
std::cout << "Calling void f(char c) "
<< "with c = '" << c << "'...\n";
}
int main()
{
f(1);
f('1');
}
/**
* Output:
* Calling void f(int)...
* Calling void f(char c) with c = '1'...
*/
Again, inside the body of void f(char c) the function call argument
/could/ be used, since it is named, but not inside the body of void
f(int).
Note: in the case of C1, even though the template parameter is not
named (and so cannot be used in the definition of the class) the
compiler still knows what the template argument is that matches it
and so it can be `reconstructed' later, elsewhere. Consider:
#include <string>
#include <iostream>
template<class> // unnamed template parameter, but...
class C1 { };
template<class T>
std::string print_type();
template<>
std::string print_type<int>()
{
return "T = int";
}
template<class T>
void f(C1<T>) // ... T can still be deduced here
{
std::cout << "Calling void f(C1<T>) with ["
<< print_type<T>()
<< "]...\n";
}
int main()
{
C1<int> c1;
f(c1);
}
/**
* Output:
2. template template parameter:
template<template<class T> class A>
struct B {
A<int> a;
};
How it differs from this one:
template<class T> class A { /* ... */ };
struct B {
A<int> a;
};
In the case of your second type B, the type of the member a is hard
coded: it is your class A. For your first type B, however, A is a
template template parameter and so it can be matched by other template
types, for instance:
template<class T> class NotA { /* ... */ };
B<NotA> b;
Note, also, that there is a difference in the syntax of declarations.
For the first you have to specify a template argument, which is not
the case for the second.
Regards
Paul Bibbings