Укажите, что функция-не-член должна вызываться вместо функции-члена.

У меня есть класс с членом под названием 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;
    }
};
Другие вопросы по тегам