如何解析模板静态成员函数? [英] 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<'
如果您更改2 Base< T>
s in Derived to Base< int>
,它编译。如果您将 Bar()
调用到 Base< T> :: template Bar< false>(5);
,它也编译。
If you change the 2 Base<T>
s in Derived to Base<int>
, it compiles. If you change the call to Bar()
to Base<T>::template Bar<false>(5);
, it also compiles.
我看到的一个解释是,编译器不知道Bar是一个模板,可能是因为它不知道Base是什么直到宣布Derived的专业化。但是一旦编译器开始生成 Foo()
的代码,已经定义了 Base< T>
的 Bar
。是什么导致编译器假设符号 Bar
是不是模板,并尝试应用 operator< / code>而不是?
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. But once the compiler starts generating code for Foo()
, Base<T>
has already been defined, and the type of Bar
can be determined. What is causing the compiler to assume the symbol Bar
is not a template, and attempting to apply operator<()
instead?
我认为它与在编译过程中评估模板时的规则 - 我猜我在找什么是一个很好的全面解释这个过程,这样下次我跑到下面的代码,我可以推导出答案没有好人的堆栈溢出的帮助。
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.
注意我使用g ++ 4.7编译,支持c ++ x11。
Note I'm compiling with g++ 4.7, with c++x11 support.
推荐答案
void Foo() { Base<T>::Bar<false>(5); }
在此上下文中 Base< T>
是依赖名称。要访问依赖名称的成员模板,您需要添加模板
关键字:
In this context Base<T>
is a dependent name. To access a member template of a dependent name you need to add the template
keyword:
void Foo() { Base<T>::template Bar<false>(5); }
否则 Base< T> :: Bar
将被解析为非模板成员,<
作为小于。
Otherwise Base<T>::Bar
will be parsed as a non-template member and <
as less-than.
为什么需要模板
,原因是两阶段查找。错误在第一遍期间被触发, 之前,类型被替换,因此编译器不会 Base< T>
。例如,您为 int
添加了具有非模板的
成员(例如, Bar
Bar int
成员)。在将 T
替换为 Foo
之前,编译器不知道是否有类型的特殊化。
As of why the template
is required, the reason is two-phase lookup. 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>
. 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). Before substituting T
into Foo
, the compiler does not know if there is an specialization for the type.
这篇关于如何解析模板静态成员函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!