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>.
Related
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.
What I want is something like std::bind for functions but for templates.
Assume I have a template which needs a template template with a defined set of arguments.
Now I have another template which would work but which has more arguments, so I need to convert this complex template into a simpler one with bound arguments.
To do this I created a template which defines an alias template.
If I use this binding template with concrete types this works well. But if I instantiate the binding template with another template argument, gcc and clang assume that the alias is not a template template. I know it becomes a dependent name, but there is nothing like the typename disambiguator for templates.
With icc and msvc this works fine.
template<
template<typename> typename Template
>
class ATypeWhichNeedsATemplateTemplate
{
};
template<typename A, typename B>
class AComplexTemplate
{
};
template<
template<typename...> typename ATemplate
,typename... Args
>
class Binder {
public:
template<typename T>
using type = ATemplate<T, Args...>;
};
template<typename T>
class AClassWithBoundTemplate : public ATypeWhichNeedsATemplateTemplate<
Binder<AComplexTemplate, T>::type
>
{
};
see on godbolt
clang complains:
<source>:30:5: error: template argument for template template parameter must be a class template or type alias template
Binder<AComplexTemplate, T>::type
^
gcc says something similar:
<source>:31:1: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class> class Template> class ATypeWhichNeedsATemplateTemplate'
>
^
<source>:31:1: note: expected a class template, got 'Binder<AComplexTemplate, T>::type'
type is a dependent template name. You need to spell it like Binder<AComplexTemplate, T>::template type, i. e.:
template<typename T>
class AClassWithBoundTemplate : public ATypeWhichNeedsATemplateTemplate<
Binder<AComplexTemplate, T>::template type
>
{
};
Fixed godbolt example: https://godbolt.org/z/7nJtAU
I have a function taking, as an argument, a template class with multiple parameters (see 'func2' in the following code). I'd like the function to be able to take as argument a class inheriting from the agument type, and automatically resolve template types by upcasting. In the following example, it's ok for function 'func1', but it's apparently not possible straightforwardly when argument is a multiple template class as for function 'func2'.
The error message states: "Candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding template template parameter"
I understand (and kind of agree) with the message. But this is the same case for 'func1', and it's working fine.
So my question is, is there a way I can treat variable 'd' as type 'C' by automatic upcasting when using a function ? And if so, how ?
I'm using Xcode 5.1.1, clang-503.0.40. and C++11 option. Thanks
template <class T1>
class A {};
class B : public A<int> {};
template <template <class T1> class T, class T1 >
void func1(T<T1> _arg) {}
template <class T1, class T2>
class C {};
template <class T1>
class D : public C<T1,int> {};
template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}
int main() {
A<int> a;
B b;
func1(a);//works
func1(b);//works, T1 is resolved
C<float,int> c;
D<float> d;
func2(c);//works
func2(d);//doesn't work,compilation error message: "Candidate template ignored: substitution failure : template template argument has different template parameters than its corresponding template template parameter"
return 0;
}
No, there's no way to do what you're trying to do.
You can use an alias though, assuming your compiler supports them:
template < typename T >
using D = C<T,int>;
I believe that should match your function template just fine.
If you're trying to have D have different behavior then you'd create a partial specialization of C.
Ok so the best option I found is as follow. The idea is to make 'D' believe it's a multiple template class, but in fact one of the template parameters is only meant to be a specific type (int). This way, 'D2' is sort of both a one template class and two template class. There's still one partial specialization when defining template class D , but it's actually only the normal definition of class D.
template <class T1, class T2>
class C {};
template <class T1, class T2=int>
class D;
template <class T1>
class D<T1,int> : public C<T1,int> {};
template <typename T1>
using D2 = D<T1>;
template <template <class T1, class T2> class T, class T1, class T2>
void func2(T<T1,T2> _arg) {}
int main()
{
C<float,int> c;
D2<float> d;
func2(c);//works
func2(d);//works
//instantiation tests:
D<float> test1;//works -> normal
D<float, int> test2;//works -> not ideal but well ok
D<float, float> test3;//doesn't work -> also normal. States: "Implicit instantiation of undefined template 'D<float, float>' "
return 0;
}
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>>
Im currently studying c++ templates and there's something I don't understand. So far I understand if you have the following generic class
template <class T> class A{
...
}
To provide a specific specialization of the class, say for int objects, you'd define the following:
template<> class A<int>{
...
}
However, I have been seeing cases similar to the following:
Original class is,
template <class T, int Size> class buffer{
...
}
Then the speciliazed class for objects of type int is,
template <int Size> class buffer<int, Size>{
...
}
I'm confused as why the specilization for int is not the following:
template<> class bufffer<int, int Size>{
...
}
Can someone please explain.
This buffer template has two template parameters. The first is a type parameter because it begins with class, and the second is a non-type parameter because it begins with int.
What you are seeing is a partial specialization on only the first parameter. Note that the template arguments for a template specialization are totally independent of the template arguments for the original template (this is one of the major things that confused me when I was learning this). For example, it would work just as well as:
template <int N> class buffer<int, N> { ... };
It is basically giving a specialization for when the first template argument of buffer is the type int and the second is some int value.
Whenever you start with template <> (empty brackets), that is an explicit specialization where you are specifying all of the template arguments. For example, you could do:
template <> class buffer<int, 1> { ... };
This would be a specialization for when the first template argument is the int type and the second is the value 1.