0

我有一个类,其中有一个名为的成员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

这当然是因为它与 member 混淆了f。然而,只有::f有意义。

如果我要强制成员函数,我可以说this->for B::f但是我不知道可以做相反的语法,即强制自由函数::f或实际上f由 ADL 给出的一些外部分辨率并禁用成员函数(类似于notthis->f)。

我可以使用using ::f

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

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

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

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

当然,我可以重命名所有内容以避免冲突,但这不是一个可接受的解决方案,假设同时调用 free 和成员函数是有意义的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;
    }
};
4

1 回答 1

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;
    }
};
于 2017-12-16T01:34:08.830 回答