c++ - 模板化静态成员函数是如何解析的?

标签 c++ templates static 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;
}

此代码无法构建,并给出错误:

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 派生到 Base<int> ,它编译。如果您将调用更改为 Bar()Base<T>::template Bar<false>(5); ,它也会编译。

我看到的对此的解释是,编译器不知道 Bar 是一个模板,大概是因为在声明 Derived 的特化之前它不知道 Base 是什么。但是一旦编译器开始为 Foo() 生成代码, Base<T>已经被定义,Bar 的类型可以确定。是什么导致编译器假定符号 Bar 不是模板,正在尝试应用 operator<()相反?

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

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

最佳答案

void Foo() { Base<T>::Bar<false>(5); } 

在此背景下 Base<T>是从属名称。要访问依赖名称的成员模板,您需要添加 template关键词:

void Foo() { Base<T>::template Bar<false>(5); } 

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

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

关于c++ - 模板化静态成员函数是如何解析的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12848155/

相关文章:

c++ - const char* 的模板方法特化

c++ - 有条件地删除模板类中的方法

c++ - 如何从相似的模板类构建对象

static - 扩展 Spring Boot WebMvcConfigurationSupport 时出现静态资源问题

c++ - 如何在 Linux 上使用 Boost.Filesystem?

c++ - 如何找出 C++ header 在 Visual Studio 中编译需要多少时间?

c++ - is_regular_file 之后我有什么保证?

c++ - C++查询类的静态成员变量

c# - 为什么我不能在公共(public)静态字符串上使用串联

c++ - GLSL shader based on KNN of external file (open external file from .vert or .frag)