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.
CodePudding user response:
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 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.