C ++ 11 estilo SFINAE y visibilidad de la función en la creación de instancias de plantilla

No estoy seguro de si esto tiene algo que ver con sfinae, o simplemente algo que sea relevante para cualquier función de plantilla. Estoy intentando usar sfinae para habilitar / deshabilitar una función miembro basada en la existencia de la función libre correspondiente, que a su vez está habilitada / deshabilitada según la existencia de la función miembro en otro tipo, todo usando el método descritoaquí:

struct S;

template <typename T>
inline auto f(S& s, T const& t)
   -> decltype(t.f(s), void())
{
   t.f(s);
}

struct S
{
    template <typename T>
    auto f(T const& t)
        -> decltype(f(*this, t), void())
    {
        f(*this, t); // <------------------------------------------- HERE
    }
};

struct pass
{
    void f(S&) const
    {
        //...
    }
};

struct fail
{
};

int main()
{
    S s;
    s.f(pass()); // should compile fine
    //s.f(fail()); // should fail to compile due to absence of f from S
    return 0;
}

sin embargo, gcc 4.7.1 me da esto en la línea marcada con una flecha:

error: no hay función coincidente para la llamada a 'S :: f (S &, const pass &)'
nota: el candidato es:
nota: plantilla decltype ((f ((* this), t), void ())) S :: f (const T &)
nota: la deducción / sustitución del argumento de la plantilla falló:
nota: el candidato espera 1 argumento, 2 proporcionado

lo que aparentemente significa que globalf Lo anterior no se considera para resolución de sobrecarga.

¿Por qué es eso y qué hago para hacerlo?

Además, ¿por qué no hay errores dos líneas por encima de eso, dondef utilizado en decltype de manera similar?

ACTUALIZAR

Como @ n.m. dicho, las funciones miembro son completamente libres de funciones, incluso cuando sus firmas son diferentes, así que aquí hay una solución que no rompe ADL paraf (a diferencia de la calificación del nombre completo sugerida por @ n.m.). Hacer función libre (f_dispatcher) en algún lugar nadie mirará (detail), y califica plenamente su nombre dentroS::f. En esa función llamada gratuita.f y dejar que ADL se encargue de eso de ahí en adelante, así:

struct S;

template <typename T>
inline auto f(S& s, T const& t)
    -> decltype(t.f(s), void())
{
    t.f(s);
}

namespace detail
{
    template <typename T>
    inline auto f_dispatcher(S& s, T const& t)
        -> decltype(f(s, t), void())
    {
        f(s, t);
    }
}

struct S
{
    template <typename T>
    auto f(T const& t)
        -> decltype(detail::f_dispatcher(*this, t), void())
    {
        detail::f_dispatcher(*this, t);
    }
};

struct pass
{
    void f(S&) const
    {
        //...
    }
};

struct fail
{
};

int main()
{
    S s;
    s.f(pass()); // compiles fine
    //s.f(fail()); // fails to compile due to absence of f from S
    return 0;
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta