繁体   English   中英

指定应调用非成员函数而不是成员函数

[英]Specify that a non-member function should be called instead of member function

我有一个名为成员的类f ,同时一个通用的自由函数调用f 自由函数f是要从另一个成员(以下称为g )调用的。

class A{};
int f(A const& a){return 5;} // generic free f

template<class T>
struct B{
    void f() const{} // member f
    int g(){
        T a;
        auto i = f(a) + 1; // here (cannot resolve f)
        return i;
    }
};

int main(){
    B<A> b; 
    int j = b.g();
    assert(j == 6);
}

事实证明,我的编译器(GCC和clang)无法解析对f的调用。

error: no matching function for call to ‘B::f(A&)’
   auto i = f(a) + 1;               ^
note: candidate: void B::f() const
  void f() const{}       ^
note:   candidate expects 0 arguments, 1 provided

当然,这是因为它与成员f混淆。 但是,只有::f才有意义。

如果要强制成员函数,可以说this->fB::f 但是我不知道有什么语法可以做相反的事情,即强制使用自由函数::f或实际上是ADL给f一些外部解析并禁用成员函数(诸如notthis->f类的东西)。

我可以使用using ::f

... int g(){
        T a;
        using ::f;
        auto i = f(a) + 1;
        return i;
    } ...

但是,这不是通用的,因为我不知道名称空间T属于哪个名称,并且我想要通用的代码。 (这里是::但是对于T = A ,但是对于其他名称空间中的其他类,我不知道)。

例如,类B<ns::C>应该编译为:

namespace ns{
    class C{};
    int f(C const& a){return 5;} // genetic free f
}

当然,我可以重命名所有内容以避免冲突,但这不是一个可以接受的解决方案,假设同时具有free和member函数f都是有意义的。

这是GCC和clang的错误,是语言的缺陷,还是我缺少一些明显的方法来指定不使用成员函数?

(该示例使用C ++ 11,但该问题对任何版本的C ++均有效)。


感谢@JohnZwinck,这是当前的解决方法

class A{};
int f(A const& a){return 5;} // genetic free f

class nonmember{
    protected:
    template<class TT> static decltype(auto) _f(TT&& t){return f(std::forward<TT>(t));}
};

template<class T>
struct B : private nonmember{
    void f() const{} // member f
    int g(){
        T a;
        auto i = _f(a) + 1;
        return i;
    }
};

这是GCC和clang的错误,是语言的缺陷吗?

以上都不是。 语言的设计决定是,名称与调用匹配的成员函数是最匹配的。 如果要避免它们,可以通过中间自由函数调用:

template<class T>
int call_f(const T& arg){
    return f(arg);
} 

template<class T>
struct B{
    void f() const{}
    int g(){
        T a;
        auto i = call_f(a) + 1;
        return i;
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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