partial specialization of template class with a template template parameter - c++

template <typename T, template <typename> class Bar>
class Foo
{
Bar<T> bar;
};
I'm trying to make a specialization of this class that would be of type Foo<Bar<Foo>> where Bar is an arbitrary template class with 1 template parameter. Can anyone show me how to do this? Also, I don't want to stick to this particular template class definition. If it can be done by using a different definition of Foo that's fine, too.
EDIT:
What I meant is that I want the specialization to be of type Foo<Foo, Bar<Foo>>

Related

How to define template template types with inheritance in C++11

I would like to define a derived class that has a template template type for a templated base class. Is this possible, and if so what is the syntax? I have tried a lot of things without success. Please consider this code:
#include <iostream>
template <typename U>
struct Wrapper {};
template <typename U>
struct Base {};
// This Works, define a template template type class
template<class>
struct Other;
template<template<typename T> typename W, typename T>
struct Other<W<T>> {};
// How do I define this?
template<template<typename T> typename W, typename T>
struct Derived : public Base<W<T>> {};
using namespace std;
int main()
{
Wrapper<float> w;
Base<int> b;
Other<Wrapper<int>> o;
Derived<Wrapper<int>> d; // fails to compile
return 0;
}
Why: I have existing/working code that has Derived<U> where U is a wrapped class W<T>. Specifying Derived<W<T>> in the definition using a template template type was unnecessary; Derived<U> is sufficient. Both W and T can be many different concrete types, but T will always have a statically available method that I now need access to from within Derived scope.
I am currently and woefully limited to C++11.
Often, things get much simpler if you realize that, for most regards, an instantiation of a class template is just a type like any other. And confusing types with templates is also the source of your error.
Wrapper<int> is a type. The first argument for the Derived template is a template, not a type.
Other is a template that has a single type argument. It has a partial specialization for the case that this type is an instantiation of some template W.
Derived is a template that has two arguments. The first is a template argument, the second is a type. An instantiation is, for example: Derived<W,int>.
If you want to make Derived a template with a single type argument, with a partial specialization for the case that this type is an instantiation of Wrapper, then you need to do the same as you did for Other: A base template with a single type argument and a specialization, eg:
template<class> struct Derived;
template<template<typename T> typename W, typename T>
struct Derived<W<T>> : public Base<W<T>> {};
The second line is the partial specialization. It does not change the fact that Derived has one type argument. It only makes Derived<W<T>> match this specialization no matter what T is.

Nested template parameters for functions

template <typename T> class foo2 {
};
Sample 1
template <typename T, template <typename> class foo2>
foo2<T> func2(){
}
Sample 2
template <template <typename T> class foo2>
foo2<T> func2(){
}
I have a template class and I would like to write a function that accepts only that class (with any of it's templates of course)
why does sample 1 works and 2 does not?
Edit:
Please provide an explanation of how the matching happens? Clearly the function in sample 1 takes two template parameters without any default values, however in the call in the main only one parameter is provided.
Edit2:
I want another func2 overload for the templated foo2 class, I already have defined in my code.
template <typename T>
T func2(){
}
Template template parameters define a template name in the body of the function. You have to provide the parameter to instantiate them. This means that the T in
template <template <typename T> class foo2> void func2(foo2<T>);
is not visible elsewhere; only the template name foo2 is.
Your first sample,
template <typename T, template <typename> class foo2> void func2(foo2<T>);
works because the T is a top-level template type parameter, which is
visible to the function body, and
deduced from the function argument.
However, this use case is more easily written with a simple template type parameter and direct use of the class foo2:
template <typename T> void func2(foo2<T>);
See, for example, template parameters and template arguments on cppreference for details
Note, the question was edited after I wrote the above, and the type is no longer used as a function argument. The point about type deduction no longer applies, but the rest of the answer stands.

template template class specialization

I am just learning about Template Template class specialisation. Not a big problem to explain in detail. From my understanding std::uniform_int_distribution is a template whereas std::uniform_int_distribution<Type> is the full specialisation of uniform_int_distribution giving a type. I pass this in the specialisation class template as follows below
Main class
template <template <class> class Distribution,
class Type,
class Engine = std::mt19937>
class random_gen
{
....
}
specialization of class
template <class Type, class Engine>
class random_gen<std::uniform_real_distribution<Type>, Type, Engine>
{
...
}
the error that occurs is:
type/value mismatch at argument 1 in template parameter list for 'template<template<class> class Distribution, class Type, class Engine> class random_gen'
The specialization still needs to be a template template argument. You passed in a full type. You want:
template <class Type, class Engine>
class random_gen<std::uniform_real_distribution, Type, Engine>
{
...
};
Just std::uniform_real_distribution, not std::uniform_distribution<Type>.

Why the common template method definition doesn't match the template class specialization?

I have the following code:
template <class T, class U = T>
class A {
public:
void f();
};
template <class T>
class A<T, T> {
public:
void f(); // Unaltered method.
// Some differences.
};
template <class T, class U>
void A<T, U>::f() {}
int main() {
A<int> a;
a.f();
return 0;
}
The clang++ -std=c++11 test.cc gives me an error: undefined reference to 'A<int, int>::f()'
Why the provided definition of method f() doesn't apply to the class A<int, int>?
The primary class template template <class T, class U = T> class A and the partial specialization template <class T> class A<T, T> are two distinct template definitions. After they've been defined, whenever you refer to the class template name A, the primary template and all partial specializations will always be considered.
Whenever you instantiate A with either a single template argument, or two arguments of the same type, it'll form a better match for the specialization you've provided, and the primary template is not considered.
In your example, because of the partial specialization you've provided, there's no way to match the primary template, regardless of the default template argument, if you try to instantiate A with a single template argument, or two of the same type.
The solution, of course, is to provide the definition for A<T, T>::f()
template <class T>
void A<T, T>::f() {}
EDIT:In the presence of partial specializations, the rules for matching them are given by (from N3797) ยง14.5.5.1/1 [temp.class.spec.match]
When a class template is used in a context that requires an
instantiation of the class, it is necessary to determine whether the
instantiation is to be generated using the primary template or one of
the partial specializations. This is done by matching the template
arguments of the class template specialization with the template
argument lists of the partial specializations.
โ€” If exactly one matching specialization is found, the instantiation is generated from that specialization.
โ€” If more than one matching specialization is found, the partial order rules (14.5.5.2) are used to determine whether one of the
specializations is more specialized than the others. ...
โ€” If no matches are found, the instantiation is generated from the primary template.
In your example the first rule applies, and the compiler doesn't even get to the 3rd rule.
When you define a member function of a class template outside the class, you are just defining the function for the corresponding function that was declared in the class template. You are not creating a new function template which might match other parameters. In your example:
template <class T, class U = T>
class A {
public:
void f(); // This is the declaration of A<T,U>::f()
};
template <class T>
class A<T, T> {
public:
void f(); // This is the declaration of A<T,T>::f()
};
template <class T, class U>
void A<T, U>::f() {} // This is the definition of A<T,U>::f()
// There is no definition of A<T,T>::f()
I believe what you are thinking is that the compiler will see that you are calling A<int,int>::f() and will look through the member function definitions and find one that matches, but this is not what happens. The compiler always looks through the class templates to find which function to call, and once it has found a match, it then looks for the corresponding definition. In your case, you are calling A<int,int>::f(), so it first looks for a class definition that matches A<int,int> and it finds your A<T,T> class template specialization. It sees that A<T,T> does indeed have a member function called f which matches your function call, which means A<T,T>::f() needs to be instantiated. To instantiate A<T,T>::f(), the compiler looks for the definition of A<T,T>::f(), however it doesn't find it. It only finds the definition of A<T,U>::f, which isn't a match. The template parameter matching that is used to find a proper function declaration doesn't apply.

what does template<> (without any class T in the <>) mean?

I'm reading some source code in stl_construct.h,
In most cases it has sth in the <>
and i see some lines with only "template<> ...".
what's this?
This would mean that what follows is a template specialization.
Guess, I completely misread the Q and answered something that was not being asked.
So here I answer the Q being asked:
It is an Explicit Specialization with an empty template argument list.
When you instantiate a template with a given set of template arguments the compiler generates a new definition based on those template arguments. But there is a facility to override this behavior of definition generation. Instead of compiler generating the definition We can specify the definition the compiler should use for a given set of template arguments. This is called explicit specialization.
The template<> prefix indicates that the following template declaration takes no template parameters.
Explicit specialization can be applied to:
Function or class template
Member function of a class template
Static data member of a class template
Member class of a class template
Member function template of a class template &
Member class template of a class template
It's a template specialization where all template parameters are fully specified, and there happens to be no parameters left in the <>.
For example:
template<class A, class B> // base template
struct Something
{
// do something here
};
template<class A> // specialize for B = int
struct Something<A, int>
{
// do something different here
};
template<> // specialize both parameters
struct Something<double, int>
{
// do something here too
};