调用模板类限定的模板函数时,即形如:A<typename_a>::member_function<typename_b>()这样的调用时;
必须使用关键字template进行说明,即改为:A<typename_a>:: template member_function<typename_b>();
否则可能报错:
error: use 'template' keyword to treat 'xx' as a dependent template name
或者
error: expected primary-expression before‘double’
上面这两个报错是对同一问题的报错,不同的编译器的提示内容可能不同。其错误代码可抽象为如下:
#include <iostream>
#include <vector>
using namespace std;
template <int dim>
struct EulerEquations //注意:这里EulerEquations是个模板类
{
template <typename number, typename InputVector> //相当于是个位于EulerEquations命名空间下的模板函数
static
number
compute_pressure (const InputVector &W)
{
return *(W.begin());
}
};
void
compute_drag()
{
std::vector<double> W(4);
W[0]=78;
W[1]=2.;
W[2]=1.5423;
W[3]=0.543;
double pressure = EulerEquations<dim>::compute_pressure<double>(W); //错误所在行
cout<<pressure;
}
int main()
{
compute_drag<2>();
return 0;
}
在上面的错误所在行,提示error: use 'template' keyword to treat 'compute_pressure' as a dependent template namedouble pressure = EulerEquations<dim>::compute_pressure<double>(W);
^
template
这句话的意思是compute_pressure模板函数在这里必须用关键字"template"进行修饰。也就是改为:
double pressure = EulerEquations<dim>::template compute_pressure<double>(W);
这样才能告诉编译器,在限定符::后面的这个函数是个模板函数,而非普通的静态函数。如果不加template关键字,则编译到这里的时候,会认为double前的<符号是小于符号,这也就是为什么有的编译器在遇到这种情况的时候会提示:error: expected primary-expression before ‘double’ double pressure = EulerEquation<dim>::compute_pressure<double>(W);
^error: expected ‘,’ or ‘;’ before ‘double’
在stackover flow上有类似的错误,比如https://stackoverflow.com/questions/3786360/confusing-template-error
其解释为:
ISO C++03 14.2/4:
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
即:当一个成员模板实例的名字(B)出现在一个后缀(下标)表达式的 .或者->之后,或者在一个qualified-id(即A::B)里的嵌套名称说明符(即A::)之后,且该后缀表达式或者qualified-id显式地依赖于某个模板参数,那么成员模板的名称必须加以关键字template。否则,该名称被假定为非模板名。
注:Given:
struct A {
struct B {
void F();
};
};
A
is an unqualified-id.::A
is a qualified-id but has no nested-name-specifier.A::B
is a qualified-id andA::
is a nested-name-specifier.::A::B
is a qualified-id andA::
is a nested-name-specifier.A::B::F
is a qualified-id and bothB::
andA::B::
are nested-name-specifiers.::A::B::F
is a qualified-id and bothB::
andA::B::
are nested-name-specifiers.
在上面的例子中:
double pressure = EulerEquations<dim>::compute_pressure<double>(W);
成员模板实例compute_pressure<double>()出现在了嵌套名称说明符(EulerEquations<dim>::)之后,且EulerEquations本身是依赖于某个模板参数的。所以必须在compute_pressure前加template,告诉编译器后面这个函数名是模板函数。
当然,如果EulerEquations不是模板类,即去掉它的template<dim>这一行,则在调用compute_pressure<double>()时不用加template。