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«

      

+3


source to share


3 answers


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?

+6


source


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.

+2


source


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.

0


source







All Articles