[英]How are templated static member functions parsed?
I have never gotten a great explanation of how template argument deduction really works, so I'm not sure how to explain behavior I'm seeing in the following: 我从来没有得到关于模板参数推导如何真正起作用的很好的解释,所以我不确定如何解释我在下面看到的行为:
template<typename T>
struct Base
{
protected:
template<bool aBool = true>
static void Bar(int)
{
}
};
template<typename T>
class Derived : public Base<T>
{
public:
void Foo() { Base<T>::Bar<false>(5); }
};
int main()
{
Derived<int> v;
v.Foo();
return 0;
}
This code won't build, and gives the error: 此代码不会构建,并给出错误:
main.cpp: In instantiation of 'void Derived<T>::Foo() [with T = int]':
main.cpp:25:8: required from here main.cpp:19:15: error: invalid
operands of types '<unresolved overloaded function type>' and 'bool'
to binary 'operator<'
If you change the 2 Base<T>
s in Derived to Base<int>
, it compiles. 如果将Derived中的2
Base<T>
更改为Base<int>
,则会进行编译。 If you change the call to Bar()
to Base<T>::template Bar<false>(5);
如果将对
Bar()
的调用更改为Base<T>::template Bar<false>(5);
, it also compiles. ,它也编译。
The one-liner I saw as an explanation for this is that the compiler doesn't know that Bar is a template, presumably because it doesn't know what Base is until a specialization of Derived is declared. 我看到的一个解释是,编译器不知道Bar是一个模板,可能是因为在声明Derived的特化之前它不知道Base是什么。 But once the compiler starts generating code for
Foo()
, Base<T>
has already been defined, and the type of Bar
can be determined. 但是一旦编译器开始为
Foo()
生成代码,就已经定义了Base<T>
,并且可以确定Bar
的类型。 What is causing the compiler to assume the symbol Bar
is not a template, and attempting to apply operator<()
instead? 是什么导致编译器假设符号
Bar
不是模板,并尝试应用operator<()
?
I assume it has to do with the rules of when templates are evaluated in the compilation process - I guess what I'm looking for is a good comprehensive explanation of this process, such that the next time I run into code like the below, I can deduce the answer without the help of the good people on stack overflow. 我假设它与在编译过程中评估模板的规则有关 - 我想我正在寻找的是对这个过程的一个很好的全面解释,这样下次我遇到如下代码时,我可以在没有堆栈溢出的好人的帮助下推断出答案。
Note I'm compiling with g++ 4.7, with c++x11 support. 注意我正在使用g ++ 4.7进行编译,支持c ++ x11。
void Foo() { Base<T>::Bar<false>(5); }
In this context Base<T>
is a dependent name. 在此上下文中,
Base<T>
是从属名称。 To access a member template of a dependent name you need to add the template
keyword: 要访问从属名称的成员模板,您需要添加
template
关键字:
void Foo() { Base<T>::template Bar<false>(5); }
Otherwise Base<T>::Bar
will be parsed as a non-template member and <
as less-than . 否则
Base<T>::Bar
将被解析为非模板成员并且<
as less-than 。
As of why the template
is required, the reason is two-phase lookup. 至于为何需要
template
,原因是两阶段查找。 The error is triggered during the first pass, before the type is substituted , so the compiler does not know what is the definition of Base<T>
. 在替换类型之前 ,第一次传递期间会触发错误,因此编译器不知道
Base<T>
的定义是什么。 Consider for example that you added an specialization of Bar
for int
that had a non-template Bar
member (say for example an int
member). 例如考虑您添加的专业化
Bar
为int
是有一个非模板Bar
成员(比方说一个int
成员)。 Before substituting T
into Foo
, the compiler does not know if there is an specialization for the type. 在将
T
替换为Foo
之前,编译器不知道该类型是否存在特化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.