Sichtbarkeit von C ++ 11-SFINAE und -Funktionen bei der Instanziierung von Vorlagen

Ich bin mir nicht sicher, ob dies irgendetwas mit sfinae zu tun hat oder nur mit etwas, das für eine Template-Funktion relevant ist. Ich versuche, sfinae zu verwenden, um eine Mitgliedsfunktion basierend auf dem Vorhandensein einer entsprechenden freien Funktion zu aktivieren / deaktivieren, die wiederum basierend auf dem Vorhandensein einer Mitgliedsfunktion in einem anderen Typ aktiviert / deaktiviert wird, alles unter Verwendung der beschriebenen MethodeHier:

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;
}

Allerdings gibt mir gcc 4.7.1 dies auf der mit Pfeil markierten Zeile:

Fehler: Keine passende Funktion für den Aufruf von 'S :: f (S &, const pass &)'
Hinweis: Kandidat ist:
note: template decltype ((f ((* this), t), void ())) S :: f (const T &)
Hinweis: Der Abzug / die Ersetzung von Vorlagenargumenten ist fehlgeschlagen:
Hinweis: Der Kandidat erwartet 1 Argument, 2 angegeben

was anscheinend bedeutet, dass globalf Oben genanntes wird für die Überlastungsauflösung nicht berücksichtigt.

Warum ist das so und was mache ich, um es dazu zu bringen?

Auch warum gibt es keine Fehler zwei Zeilen darüber, wof in decltype in ähnlicher Weise verwendet?

AKTUALISIEREN

As @ n.m. Die Member-Funktionen haben keine Schatten, auch wenn ihre Signaturen unterschiedlich sind. Hier ist eine Problemumgehung, die ADL nicht beeinträchtigtf (Im Gegensatz zu der von @ n.m. vorgeschlagenen vollständigen Namensqualifikation). Machen freie Funktion (f_dispatcher) irgendwo wird niemand hinsehen (detail), und geben Sie den Namen vollständig einS::f. In dieser Funktion kostenlos anrufenf und lassen Sie ADL von da an so vorgehen:

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;
}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage