如何解析模板化的静态成员函数?

Rol*_*lie 5 c++ static templates c++11

我从来没有得到关于模板参数推导如何真正起作用的很好的解释,所以我不确定如何解释我在下面看到的行为:

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;
}
Run Code Online (Sandbox Code Playgroud)

此代码不会构建,并给出错误:

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<'
Run Code Online (Sandbox Code Playgroud)

如果您将Base<T>Derived中的2更改为Base<int>,则编译.如果您将呼叫更改Bar()Base<T>::template Bar<false>(5);,则它也会编译.

我看到的一个解释是,编译器不知道Bar是一个模板,可能是因为在声明Derived的特化之前它不知道Base是什么.但是一旦编译器开始生成代码Foo(),Base<T>已经定义了,并且Bar可以确定类型.是什么原因造成的编译器采用的符号Bar不是一个模板,并尝试应用operator<()呢?

我假设它与在编译过程中评估模板的规则有关 - 我想我正在寻找的是对这个过程的一个很好的全面解释,这样下次我遇到如下代码时,我可以在没有堆栈溢出的好人的帮助下推断出答案.

注意我正在使用g ++ 4.7进行编译,支持c ++ x11.

Dav*_*eas 3

void Foo() { Base<T>::Bar<false>(5); } 
Run Code Online (Sandbox Code Playgroud)

在这种情况下Base<T>是一个从属名称。要访问从属名称的成员模板,您需要添加关键字template

void Foo() { Base<T>::template Bar<false>(5); } 
Run Code Online (Sandbox Code Playgroud)

否则Base<T>::Bar将被解析为非模板成员<小于。

至于为什么template需要,原因是两阶段查找。该错误是在类型被替换之前的第一遍期间触发的,因此编译器不知道的定义是什么Base<T>。例如,考虑您添加了Bar具有int非模板Bar成员(例如成员int)的专门化。在替换Tinto之前Foo,编译器不知道该类型是否有专门化。