Reputation: 16310
I have a class with a member called f
and simultaneously a generic free function called f
.
The free function f
is meant to called from another member (called g
below).
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);
}
It turns out that my compilers (GCC and clang) can't resolve the call to 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
This is of course because it gets confused with the member f
.
Yet, only ::f
makes sense.
If I were to force the member function, I could say this->f
or B::f
.
However I know no syntax that can do the opposite, i.e. force the free function ::f
or actually some external resolution to f
given by ADL and disable the member function (something like notthis->f
).
I could use using ::f
:
... int g(){
T a;
using ::f;
auto i = f(a) + 1;
return i;
} ...
But, this wouldn't be generic because I don't know to which namespace T
belongs and I want generic code. (here it is ::
but for T = A
, but for other classes in other namespaces I don't know).
For example, the class B<ns::C>
should compile for:
namespace ns{
class C{};
int f(C const& a){return 5;} // genetic free f
}
Of course I could rename everything to avoid the clash but that is not an acceptable solution, suppose that it makes sense to have both the free and the member function called f
.
Is this a bug on GCC and clang, a defect on the language or am I missing some obvious way to specify to not use the member function?
(the example uses C++11 but the question is valid for any version of C++).
Thanks to @JohnZwinck, this is the current workaround
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;
}
};
Upvotes: 0
Views: 206
Reputation: 249552
Is this a bug on GCC and clang, a defect on the language?
None of the above. It is a design decision within the language that member functions whose names match the call are the best match. If you want to avoid them, you can call through an intermediate free function:
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;
}
};
Upvotes: 2