为什么这段代码在g++中无法编译?

7

以下示例代码未在g++中编译,但在Visual Studio上运行良好。 在g++中是否可以在模板类中使用模板成员函数?

class Impl
{
public:
        template<class I>
        void Foo(I* i)
        {

        }
};

template<class C>
class D
{
public:
        C c;
        void Bar()
        {
                int t = 0;
                c.Foo<int>(&t);
        }
};

int main()
{
        D<Impl> d;
        d.Bar();
        return 0;
}

5
你看到了哪些错误? - Nick
2个回答

9

因为所讨论的语句取决于一个模板参数,编译器在实例化之前不允许内省C。你必须告诉它你指的是一个函数模板:

c.template Foo<int>(&t);

如果你没有放置template,该语句会变得模糊不清。 为了理解,想象一下以下的C代码:
class C { const int Foo = 5; }; 
...
c.Foo<int>(&t);

编译器认为您正在将一个const intint进行比较,并将比较结果与一些&t的地址进行比较:(c.Foo<int) > &t

真正的解决方案是在函数调用中省略显式模板参数,只需执行以下操作:

c.Foo(&t);

即使这个“C”有一个非模板成员函数“Foo(int)”,这也是正确的。通常,编写模板代码时应尽量少地做出假设(但不要少于这个数量)。

4

Foo()是一个依赖于模板的名称,因此您需要在调用前面加上template

template<class C>
void D<C>::Bar()
{
    int t = 0;
    c.template Foo(&t);
}

你也可以省略 <int>,直接使用 c.Foo(&t)。这样也应该可以正常工作。 - evnu
@evnu同意省略<int>(就像我在我的回答中所做的那样),但不同意省略template(就像你在评论中所做的那样)。 - Michael Wild
@MichaelWild:当然可以省略 template - Sebastian Mach
@MichaelWild:不要强迫提问者接受你的答案,特别是如果问题只有几分钟的时间。这是自私的行为。 - Sebastian Mach
1
另一点:如果 c.Foo() 不是一个模板,那么省略 template 的版本也是正确的,这就是我更喜欢它的原因。 - Sebastian Mach
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接