I'm having difficulty understanding the syntax of C++ Template Template parameters. I understand why they are useful, as per the excellent description here, I just find their syntax hard to get to understand. Two examples taken from the above website (there are others):
template <typename T, template <typename> class Cont>
class Stack;
and
template <template <typename,typename> class Cont>
class Wrapper3;
Clearly generalizing such declarations is impossible without some understanding of the rationale behind this syntax. Memorizing is harder and does not seem to be of much help.
Edit:
I realize that my attempt at a question came across like an observation. What I'm asking for is help on how to interprete the Template Template parameter syntax in everyday speak. I can do this with the C++ syntax and the all the other programming languages that I've learned. However I'm having difficulty "explaining" the syntax of C++ Template Template parameters to myself. I've gotten a book, "C++ templates : the complete guide" by David Vandevoorde and Nicolai M. Josuttis, and while its a nice book, it hasn't been of much help to me in understanding this syntax which I'm sure many will agree is at best quirky.
I am not sure what is your question exactly, but here is the explanation for the two examples you gave.
template <typename T, template <typename> class Cont>
class Stack;
Stack is a class template with two template parameters. The first parameter, T can be any type (including built-in types, user-defined types, template instantiations and so on). The second parameter, Cont, must be a class template taking one parameter. The parameter is unnamed because it would not make much sense (the parameter is never bound to anything).
template <template <typename,typename> class Cont>
class Wrapper3;
Wrapper3 is a class template with a single parameter, Cont. Cont must be a class template with two parameters.
The syntax to define a template template parameter is the same as the one to define a class template (template <typename [param1], typename [param2], ...> class Name), so I don't really understand what is your problem.
However, I agree that the syntax can become a bit awkward when you start "nesting" template template parameters:
// class template whose parameter must be a class template whose parameter
// must be a class template
template <template <template <typename> class > class C >
struct Wow {};
Doesn't happen that often, though...
There's nothing so arcane about it. Just take out your template template parameters from the original template:
template <typename> class Cont
Any class template with a single type argument fits, such as
template <typename T>
class A {
public:
A(T t) : t_(t) {}
T get() { return t_; }
private:
T t_;
};
And you would use your original template as
Stack<int, A> s;
Related
Reading this question made me wonder: is there a technical reason for disallowing class templates overloads?
By overloading, I mean having several templates with the same names, but different parameters, for instance
template <typename T>
struct Foo {};
template <typename T1, typename T2>
struct Foo {};
template <unsigned int N>
struct Foo {};
The compiler manages to handle overloaded functions and function templates, wouldn't it be possible to apply the same techniques (e.g. name mangling) to class templates?
At first, I thought that perhaps that would cause some ambiguity issues when taking the template identifier alone, but the only time this can happen is when passing it as a template template argument, so the type of the parameter could be used to choose the appropriate overload:
template <template <typename> class T>
void A {};
template <template <unsigned int> class T>
void B {};
A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>
Do you think such feature could be useful? Is there some "good" (i.e. technical) reasons why this is not possible in current C++?
Section 12.5 from Templates the Complete Guide (Amazon) contains this quote:
You may legitimately wonder why only class templates can be partially specialized. The reasons are mostly historical.
It is probably possible to define the same mechanism for function templates (see Chapter 13).
In some ways the
effect of overloading function templates is similar, but there are also some subtle differences. These differences are
mostly related to the fact that the primary template needs to be
looked up when a use is encountered. The specializations are
considered only afterward, to determine which implementation should be
used.
In contrast, all overloaded function templates must be brought
into an overload set by looking them up, and they may come from
different namespaces or classes. This increases the likelihood of
unintentionally overloading a template name somewhat.
Conversely, it
is also imaginable to allow a form of overloading of class templates.
Here is an example:
// invalid overloading of class templates
template<typename T1, typename T2> class Pair;
template<int N1, int N2> class Pair;
However, there doesn't seem to be a pressing need for
such a mechanism.
Furthermore, the Design and Evolution of C++ (Amazon) contains this quote in section 15.10.3
I therefore concluded that we needed a mechanism for "specializing"
templates. This could be done either by accepting general overloading
or by some more specific mechanism. I chose a specific mechanism
because I thought I was primarily addressing irregularities caused by
irregularities in C and because suggestions of overloading invariably
creates a howl of protests. I was trying to be cautious and
conservative; I now consider that a mistake. Specialization as
originally defined was a restricted and anomalous form of overloading
that fitted poorly with the rest of the language.
Bold emphasis mine. I interpret this as saying that function overload resolution is more difficult to implement (and get right by users) than class specialization. So probably no real technical obstacles (similary for function template partial specialization) but an historical accident.
You cannot "overload" type parameter, non-type argument and template template parameter, but you can specialize variadic template:
template <typename... T>
struct Foo;
template <typename T1>
struct Foo<T1> {};
template <typename T1, typename T2>
struct Foo<T1,T2> {};
This has been around for a while now, but I still found this post when searching. Thanks to #log0 for providing me with a good start. Here is a solution that avoids needing to provide a template specialisation for all possible enumerations. It does make one assumption: that you can define each template expansion in terms of itself and its base classes. (This would be done in FooImpl below):
template <typename... T>
struct Foo;
template<typename T>
struct Foo<T> { /* implementation of base class goes here*/};
template <typename C, typename Base>
struct FooImpl : public Base { /* implementation of derived class goes here */};
template<typename C, typename... Bases>
struct Foo<C, Bases...> : FooImpl<C, Foo<Bases...> > { /*NO IMPLEMENTATION HERE */};
The use of FooImpl breaks the ambiguous recursion that otherwise results. This then allows declarations such as the following:
Foo<int> foo_int;
Foo<int, double> foo_int_double;
Foo<int, float, double> foo_int_float_double;
Perhaps this is how the STL now does it?
I recently asked a question about determining whether an iterator points to a complex value at compile time and received an answer that works.
The question is here:
How can I specialize an algorithm for iterators that point to complex values?
And the solution was a set of templates that determine whether one template is a specialization of another:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
This does work, but I am really struggling to understand how this works. Particularly the nested template within a template is confusing to me. I'm also still fairly new to using variadic templates and it seems odd to have a variadic template with no type provided, for example: <class...> instead of something like this <class... Args>.
Can someone please break down this template and describe how it gets resolved?
You have to take in count that there are three types of template parameters:
1) types
2) non-types (or values)
3) template-templates
The first type is preceded by typename (or class)
template <typename T>
void foo (T const & t);
In the preceding example, T is a type and t (a classical function argument) is a value of type T.
The second type of template parameter are values and are preceded by the type of the value (or auto, starting from C++17, for a not specified type)
template <int I>
void bar ()
{ std::cout << I << std::endl; }
In the preceding example the I template parameter is a value of type int.
The third type is the most complex to explain.
Do you know (I suppose) that std::vector<int> and std::vector<double> are different types, but they have in common std::vector, a template class.
A template-template parameter is a parameter that accept std::vector, the template class without arguments.
A template-template parameter is preceded by a template keyword, as in the following example
template <template <int> class C>
void baz ();
The template-template parameter C in the preceding example is class (or struct) that require a single int (value) template parameter.
So if you have a class
template <int I>
class getInt
{ };
you can pass getInt, as template parameter, to baz()
baz<getInt>();
Now you should be able to understand your code:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
the is_specialization struct is a template struct that receive, as template parameters, a type (T) and a template-template Template that accept classes/structs receiving a variadic number of type template parameters.
Now you have a specialization of is_specialization:
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
This specialization is selected when the first template parameter (Template<Args...>) is a class based on the second (Template).
An example: if you instantiate
is_specialization<std::vector<int>, std::map>
the main version (that inherit from std::false_type) is selected because std::vector<int> isn't based on std::map.
But if you instantiate
is_specialization<std::vector<int>, std::vector>
the specialization (that inherit from std::true_type) is selected because std::vector<int> is based on std::vector.
This is a answer based on what caused "click" in my head when it comes to this, I am sure max66 answer is much more useful if you can follow it. If like me even after reading about this you are still strugling here is my attempt to explain this.
Do not read the first lines of templates
So this:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
becomes this:
struct is_specialization : std::false_type {};
struct is_specialization<Template<Args...>, Template> : std::true_type {};
Now things are bit simpler. We have first general case, and second special case(that is prefered by compiler when he can match the arguments).
By match I do not mean anything fancy, almost literal text matching.
So for example if we do
is_specialization<std::vector<double>, std::set>
Now compiler will try to match special case.
You can imagine it literally replacing the Template with std::vector (if he is matching on the first argument first), and then fail since he now expects Template to mean std::vector and in the second argument it is std::set.
He also replaced Args... with double but that is not so important since that is not the cause of mismatch.
Similarly compiler could have first tried to match second argument and conclude that Template must be std::set, and then he fails since first argument is not std::set<Args...>.
I consider the first lines of templates much less important and easier to understand, but for completeness let's go over them.
template <class T, template <class...> class Template>
Just means that this is a template whose second arg is template template argument, this is needed so you can pass something like std::set as second argument(note that normally this will not work, you would need to pass std::set of some type, e.g. std::set<float>).
The ugliest part is the first line of second template:
template <template <class...> class Template, class... Args>
Here again if we remember what we do in specialization code makes sense.
We have template template argument Template, and Args are needed just because we want to use template template argument as normal template argument(as first arg(Template<Args...>)).
tl;dr
Ignore first lines of template, pattern match.
Disclaimer: Like I said this is just my way of explaining this code to myself, I know that standard people would cry reading phrases like "first line" or "pattern match".
Suppose we have the following code:
template<typename T>
class C
{};
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{};
int main(int argc, char* argv[])
{
C<int> c;
dummyMe(c);
return 0;
}
Which doesn't compile due to the first dummyMe argument being an rvalue-reference. Could someone explain me in Standardese why the template template parameters are not getting along with the forwarding references and why is it so in plain English.
P.S. I've stumbled on this and that questions but I do not see any real proofs in the answers.
An answer from the link above and the answer to this question assert that Container<T> can't be counted as a template parameter. And I see no reason why it is so. Let's make the example even simpler:
template <template <typename=int> class Container>
void dummyMe(Container<>&&)
{};
Now we have an example almost identical to the following:
template <typename Container>
void dummyMe(Container&&)
{};
But which is treated in a completely different fashion. Why? Why is Container<>&& can't be considered as the same thing to template <typename=int> class Container as Container&& to typename Container?
The term "forwarding reference" is described at [temp.deduct.call/3](from C++17 draft n4659):
A forwarding reference is an rvalue reference to a cv-unqualified
template parameter that does not represent a template parameter of a
class template (during class template argument deduction).
In your example Container<T> is not a template parameter, it is a type you comprised from the template parameters T and Container. In order for the reference to be truly forwarding, you can use T&& only. While Conatiner is a template parameter, you can't have a reference to a template (the above paragraphs even mentions it explicitly). The type Container<T> is not the same as the template Container. It's an instantiated class.1
While you can use SFINAE to obtain a forwarding reference that can be bound only to the container type, I personally feel you're better off just overloading the function.
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{}
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&)
{}
1[temp.spec/2] - A class instantiated from a class template is called an instantiated class
An answer from the link above and the answer to this question assert that Container<T> can't be counted as a template parameter
What is or is not a template parameter is not subject to much interpretation. It is clearly defined in [temp.param]:
template-parameter:
type-parameter
parameter-declaration
type-parameter:
type-parameter-key ...(opt) identier (opt)
type-parameter-key identier(opt) = type-id
template < template-parameter-list > type-parameter-key ...(opt) identier(opt)
template < template-parameter-list > type-parameter-key identier(opt) = id-expression
type-parameter-key:
class
typename
It is clear from these production rules that dummyMe has exactly two template parameters: typename T and template <typename> class Container. Identifiers that name each of these parameters are T and Container. T names the first parameter and Container names the second one. Container<T> is not an identifier and names neither of the two.
Reading this question made me wonder: is there a technical reason for disallowing class templates overloads?
By overloading, I mean having several templates with the same names, but different parameters, for instance
template <typename T>
struct Foo {};
template <typename T1, typename T2>
struct Foo {};
template <unsigned int N>
struct Foo {};
The compiler manages to handle overloaded functions and function templates, wouldn't it be possible to apply the same techniques (e.g. name mangling) to class templates?
At first, I thought that perhaps that would cause some ambiguity issues when taking the template identifier alone, but the only time this can happen is when passing it as a template template argument, so the type of the parameter could be used to choose the appropriate overload:
template <template <typename> class T>
void A {};
template <template <unsigned int> class T>
void B {};
A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>
Do you think such feature could be useful? Is there some "good" (i.e. technical) reasons why this is not possible in current C++?
Section 12.5 from Templates the Complete Guide (Amazon) contains this quote:
You may legitimately wonder why only class templates can be partially specialized. The reasons are mostly historical.
It is probably possible to define the same mechanism for function templates (see Chapter 13).
In some ways the
effect of overloading function templates is similar, but there are also some subtle differences. These differences are
mostly related to the fact that the primary template needs to be
looked up when a use is encountered. The specializations are
considered only afterward, to determine which implementation should be
used.
In contrast, all overloaded function templates must be brought
into an overload set by looking them up, and they may come from
different namespaces or classes. This increases the likelihood of
unintentionally overloading a template name somewhat.
Conversely, it
is also imaginable to allow a form of overloading of class templates.
Here is an example:
// invalid overloading of class templates
template<typename T1, typename T2> class Pair;
template<int N1, int N2> class Pair;
However, there doesn't seem to be a pressing need for
such a mechanism.
Furthermore, the Design and Evolution of C++ (Amazon) contains this quote in section 15.10.3
I therefore concluded that we needed a mechanism for "specializing"
templates. This could be done either by accepting general overloading
or by some more specific mechanism. I chose a specific mechanism
because I thought I was primarily addressing irregularities caused by
irregularities in C and because suggestions of overloading invariably
creates a howl of protests. I was trying to be cautious and
conservative; I now consider that a mistake. Specialization as
originally defined was a restricted and anomalous form of overloading
that fitted poorly with the rest of the language.
Bold emphasis mine. I interpret this as saying that function overload resolution is more difficult to implement (and get right by users) than class specialization. So probably no real technical obstacles (similary for function template partial specialization) but an historical accident.
You cannot "overload" type parameter, non-type argument and template template parameter, but you can specialize variadic template:
template <typename... T>
struct Foo;
template <typename T1>
struct Foo<T1> {};
template <typename T1, typename T2>
struct Foo<T1,T2> {};
This has been around for a while now, but I still found this post when searching. Thanks to #log0 for providing me with a good start. Here is a solution that avoids needing to provide a template specialisation for all possible enumerations. It does make one assumption: that you can define each template expansion in terms of itself and its base classes. (This would be done in FooImpl below):
template <typename... T>
struct Foo;
template<typename T>
struct Foo<T> { /* implementation of base class goes here*/};
template <typename C, typename Base>
struct FooImpl : public Base { /* implementation of derived class goes here */};
template<typename C, typename... Bases>
struct Foo<C, Bases...> : FooImpl<C, Foo<Bases...> > { /*NO IMPLEMENTATION HERE */};
The use of FooImpl breaks the ambiguous recursion that otherwise results. This then allows declarations such as the following:
Foo<int> foo_int;
Foo<int, double> foo_int_double;
Foo<int, float, double> foo_int_float_double;
Perhaps this is how the STL now does it?
For templates I have seen both declarations:
template < typename T >
template < class T >
What's the difference?
And what exactly do those keywords mean in the following example (taken from the German Wikipedia article about templates)?
template < template < typename, typename > class Container, typename Type >
class Example
{
Container< Type, std::allocator < Type > > baz;
};
typename and class are interchangeable in the basic case of specifying a template:
template<class T>
class Foo
{
};
and
template<typename T>
class Foo
{
};
are equivalent.
Having said that, there are specific cases where there is a difference between typename and class.
The first one is in the case of dependent types. typename is used to declare when you are referencing a nested type that depends on another template parameter, such as the typedef in this example:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
The second one you actually show in your question, though you might not realize it:
template < template < typename, typename > class Container, typename Type >
When specifying a template template, the class keyword MUST be used as above -- it is not interchangeable with typename in this case (note: since C++17 both keywords are allowed in this case).
You also must use class when explicitly instantiating a template:
template class Foo<int>;
I'm sure that there are other cases that I've missed, but the bottom line is: these two keywords are not equivalent, and these are some common cases where you need to use one or the other.
For naming template parameters, typename and class are equivalent. §14.1.2:
There is no semantic difference
between class and typename in a
template-parameter.
typename however is possible in another context when using templates - to hint at the compiler that you are referring to a dependent type. §14.6.2:
A name used in a template declaration
or definition and that is dependent on
a template-parameter is assumed not to
name a type unless the applicable name
lookup finds a type name or the name
is qualified by the keyword typename.
Example:
typename some_template<T>::some_type
Without typename the compiler can't tell in general whether you are referring to a type or not.
While there is no technical difference, I have seen the two used to denote slightly different things.
For a template that should accept any type as T, including built-ins (such as an array )
template<typename T>
class Foo { ... }
For a template that will only work where T is a real class.
template<class T>
class Foo { ... }
But keep in mind that this is purely a style thing some people use. Not mandated by the standard or enforced by compilers
No difference
Template type parameter Container is itself a template with two type parameters.
There is no difference between using <typename T> OR <class T>; i.e. it is a convention used by C++ programmers. I myself prefer <typename T> as it more clearly describes its use; i.e. defining a template with a specific type.
Note: There is one exception where you do have to use class (and not typename) when declaring a template template parameter:
template <template <typename> class T> class C { }; // valid!
template <template <typename> typename T> class C { }; // invalid!
In most cases, you will not be defining a nested template definition, so either definition will work -- just be consistent in your use.
This piece of snippet is from c++ primer book. Although I am sure this is wrong.
Each type parameter must be preceded by the keyword class or typename:
// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);
These keywords have the same meaning and can be used interchangeably inside a template parameter list. A template parameter list can use both keywords:
// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);
It may seem more intuitive to use the keyword typename rather than class to designate a template type parameter. After all, we can use built-in (nonclass) types as a template type argument. Moreover, typename more clearly indicates that the name that follows is a type name. However, typename was added to C++ after templates were already in widespread use; some programmers continue to use class exclusively