Using static templates of template elements
Why won't this code compile?
struct A {
template <class T>
static T a(int i) { return 2*i; }
};
template <class T>
struct B {
double b;
B(): b(T::a<double>(5)) {}
};
template class B<A>;
The compiler doesn't even reach the template instance. I am using gcc 4.7.0.
test.cc: In constructor »B<T>::B()«:
test.cc:9:25: Error: expected »(« before »<« token
test.cc:9:26: Error: expected primary-expression before »double«
source to share
You are missing a keyword template
because it a
is a dependent name (or something like that).
B(): b(T::template a<double>(5)) {}
(Also your last line should be template struct B<A>;
.)
For details on the details see: Where and why do I need to put a "template"? and "typename" keywords?
source to share
You must put template
before the method name:
B(): b(T::template a<double>(5)) {}
This is because when parsing a template, the B
compiler does not know what T::a
the template is (since it is T
not specified until then, but is T::a
completely unknown), so it does not know what <double>
to parse as a list of template parameters.
It can also mean and indeed will be parsed as: T::a
less is double
more than (0)
. Of course double
not an expression, so it fails; thus the error message. Therefore, the compiler may simply assume that you want it to be a templated function call. But you can also have a non-python type template parameter, say for example int, so T::a<42>(5)
can be parsed as T::a
less than 42
greater than (5)
, which is not a template. But you wanted it to be parsed as T::a
, then a template parameter list with a parameter 42
, and then a call statement with an argument 5
.
To tell the compiler that this is a templated function call, you must place template
before the function name.
source to share
The compiler doesn't know anything about T. So every time you write T::{something}
it assumes that it {something}
is either a member variable or a method of T. If it isn't, you have to tell it what it is. You probably know about the keyword typename
that you should use when it comes to a type, not a variable. There's a similar trick for template members:
template <class T>
struct B {
double b;
B(): b(T::template a<double>(5)) {}
};
The compiler now knows what a
is a template and what after that is a list of template parameters.
source to share