在类模板参数上调用模板方法

Pet*_*r H 2 c++ templates

放入 .cpp 文件中的以下最小示例会导致 VisualStudio 2017(15.7.4,启用 /std:c++17)中出现编译器错误:

template <typename T>
class A
{
    void f(T& t)
    {
        t.g<2>();
    }
};

// B is a candidate for the template parameter T in A
struct B {
    template <int a>
    void g() {
        // nothing here
    }
};
Run Code Online (Sandbox Code Playgroud)

编译器错误引用 A::f() 的主体并显示:

error C2760: syntax error: unexpected token ')', expected 'expression' .
Run Code Online (Sandbox Code Playgroud)

请注意,A 和 B 都没有实际实例化。不声明 B 也会发生同样的错误。

但是,如果我切换声明 A 和 B 的顺序,则该示例将编译(并且可以实例化 A)。这很令人惊讶,因为我没有在代码中表达 A 和 B 之间的任何关系。另一个令人惊讶的事实是,将参数(例如 int)添加到 B::g() 的签名和 g() 的调用似乎也解决了错误(不改变声明的顺序)。

我的问题是:(1)为什么上面的代码会产生编译器错误?(2) 我怎样才能干净利落地解决这个问题?

Kla*_*aus 5

如果在模板类中使用模板,则必须告诉编译器这是一个模板。

template <typename T>
class A
{
    void f(T& t)
    {
        t.template g<2>();
    }
 };
Run Code Online (Sandbox Code Playgroud)

关于.template::template用法的一个很好的解释可以在这里找到:Where and Why do I have to put the "template" and "typename" keywords?