Укажите, что функция-не-член должна вызываться вместо функции-члена.
У меня есть класс с членом под названием 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->f
или же B::f
, Однако я не знаю синтаксиса, который может сделать противоположное, то есть заставить свободную функцию ::f
или на самом деле какое-то внешнее разрешение f
дано ADL и отключить функцию-член (что-то вроде 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
,
Это ошибка в 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 ответ
Это ошибка в 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;
}
};