What is the correct syntax to use template parameters of a template class argument in another template class?
For example: How can I access X and Y of class Param in class Foo?
Program:
template < template < int, int > class X1>
struct Foo {
int foo() {
printf("ok%d %d\n", X1::X, X1::Y);
return 0;
}};
template < int X, int Y >
class Param {
int x,y;
public:
Param(){x=X; y=Y;}
void printParam(){
cout<<x<<" "<<y<<"\n";
}
};
int main() {
Param<10, 20> p;
p.printParam();
Foo< Param > tt;
tt.foo();
return 0;
}
As such for the above code, for the printf statement compiler complains:
In member function 'int Foo<X1>::foo()':
Line 4: error: 'template<int <anonymous>, int <anonymous> > class X1' used wit开发者_如何学Chout template parameters
compilation terminated due to -Wfatal-errors.
You can't. The template template parameter means that you take a template name without supplied template arguments.
Foo< Param > tt;
Here you can see that no values are supplied for Param
. You'd take a template template parameter so that Foo itself could instantiate Params
with any arguments it likes.
Example:
template < template < int, int > class X1>
struct Foo {
X1<1, 2> member;
X1<42, 100> foo();
};
template <int N, int P> struct A {};
template <int X, int Y> struct B {};
Foo<A> a_foo; //has a member of type A<1, 2>, foo returns A<42, 100>
Foo<B> b_foo; //has a member of type B<1, 2>, foo returns B<42, 100>
But if you want your Foo
to output those integers, it has to take real types, not templates. Secondly, the names of the template arguments (X
and Y
) are only meaningful where they are in scope. They are otherwise completely arbitrary identifiers. You can retrieve the values with simple metaprogramming:
#include <cstdio>
template <class T>
struct GetArguments;
//partial specialization to retrieve the int parameters of a T<int, int>
template <template <int, int> class T, int A, int B>
struct GetArguments<T<A, B> >
{
enum {a = A, b = B};
};
//this specialization also illustrates another use of template template parameters:
//it is used to pick out types that are templates with two int arguments
template <class X1>
struct Foo {
int foo() {
printf("ok%d %d\n", GetArguments<X1>::a, GetArguments<X1>::b);
return 0;
}
};
template < int X, int Y >
class Param {
public:
void print();
};
//this is to illustrate X and Y are not essential part of the Param template
//in this method definition I have chosen to call them something else
template <int First, int Second>
void Param<First, Second>::print()
{
printf("Param<%d, %d>\n", First, Second);
}
int main() {
Foo< Param<10, 20> > tt;
tt.foo();
Param<10, 20> p;
p.print();
return 0;
}
This here is an example what could work as well:
template < typename X1>
struct Foo;
template < template < int, int > class X1, int X, int Y >
struct Foo< X1<X,Y> > {
int foo() {
printf("ok%d %d\n", X, Y);
return 0;
}
};
template < int X, int Y >
class Param {
int x,y;
public:
Param(){x=X; y=Y;}
void printParam(){
cout<<x<<" "<<y<<"\n";
}
};
int main() {
Param<10, 20> p;
p.printParam();
Foo< Param<30,40> > tt;
tt.foo();
return 0;
}
You can't take template parameters of a template class argument, since the argument is a template without parameters. You can do this instead:
template < typename X1 >
struct Foo;
template < template < int, int > class X1, int A, int B >
struct Foo< X1< A, B > >
{
... here you can use A and B directly, or X1< A, B >::X and X1< A, B >::Y ...
};
You specify the template to take a single type, and specialize it for the case of a template taking two int
arguments. With that definition, you would use it like this:
Foo< Param< 0, 1 > > tt;
精彩评论