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

时间:2017-12-16 01:25:05

标签: c++ c++11 member-functions argument-dependent-lookup non-member-functions

我有一个名为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
}

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

这是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;
    }
};

1 个答案:

答案 0 :(得分:2)

  

这是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;
    }
};