简体   繁体   English

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

[英]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). 例如考虑您添加的专业化Barint是有一个非模板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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM