【问题标题】:Need scope resolution operator to call member function template when class template exists with same name当类模板存在同名时,需要范围解析运算符来调用成员函数模板
【发布时间】:2013-05-09 12:48:15
【问题描述】:

我有一个类模板,它恰好与某些类的成员函数模板同名。现在,另一个函数模板被实例化为具有相关成员函数模板的类之一。要在这个函数模板中调用成员函数模板我需要使用template 关键字,我理解这一点并且对此没有问题。但是,我需要使用范围解析运算符(我刚刚发现这就是所谓的):: 来指定我的意思是类的成员函数模板而不是类模板,我不明白为什么。

这是很多模板化的东西,所以让我举个例子:

    //class with same name as member function below.
    //must be class template or error doesn't show up.
    //also no error if this is a function template instead of class
    template <class T>
    struct f
    {
    };

    struct Base
    {
        //function with same name as struct above,
        //no error if this is not templated
        template <int N>
        void f(){}
    };

    //template function that will be instantiated with T=Base.
    //no error if this is not templated
    template <class T>
    void g(T t)
    {
        //I understand why template keyword is needed here,
        //but not why T:: is needed
        t.T::template f<0>();
        //t.template f<0>(); gives error.
    }

有问题的错误是(来自 g++-4.7)

    error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> struct f’
    error:   expected a type, got ‘0’

编译器似乎将注释掉的行(没有范围解析运算符)上的f&lt;0&gt;() 解析为试图实例化struct f&lt;0&gt; 类型的对象。不知道为什么会这样,我想应该可以从t.template看到我正在尝试访问成员函数模板。

我想了解这里发生了什么,为什么在这种情况下需要T::,而不是为了安抚编译器?

MSVC和Clang下好像没有问题,所以好像是g++特有的问题。

【问题讨论】:

    标签: c++ g++


    【解决方案1】:

    我认为这与Two phase lookup 有关。尤其是 Steve Jessops 在答案中的注释很重要。

    【讨论】:

    • 你是说它在第一阶段跳闸了吗?语法(在第一阶段检查的内容)t. template f&lt;0&gt;() 如何可能引用struct f 使得T:: 是消除歧义所必需的?
    • @GuyGreer 是的,我认为它看到 f 并将其解释为非依赖名称并且无法实例化模板。另一方面,msvc 没有实现两阶段查找,也没有错误。我尝试了 clang 3.0(在 linux 上),它也可以编译。
    • clang 编译甚至 t.f();
    • 来自 [temp.dep.type]/8 如下:T 是依赖类型。从 [temp.dep.expr]/1+3 如下:任何涉及 t 的表达式都是类型相关的。从 [temp.dep]/1 如下:在t.template f&lt;0&gt;() 中,t.template f&lt;0&gt; 是一个从属名称。
    【解决方案2】:

    这可能有效

    template <class T>
    void g(T t)
    {
        t.T::template f<0>(); 
    }
    

    【讨论】:

    • 尝试在您的main() 中调用g(Base());。它会失败,因为它找不到Base::f()
    • 这正是我所说的。问题是问为什么需要T::
    猜你喜欢
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2021-08-09
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多