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