SFINAE w stylu C ++ 11 i widoczność funkcji w instancji szablonu
Nie jestem pewien, czy ma to coś wspólnego z sfinae, czy po prostu coś, co jest istotne dla każdej funkcji szablonowej. Próbuję użyć sfinae, aby włączyć / wyłączyć funkcję składową opartą na istnieniu odpowiedniej wolnej funkcji, która z kolei jest włączona / wyłączona na podstawie istnienia funkcji składowej w innym typie, wszystko przy użyciu opisanej metodytutaj:
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;
}
jednak gcc 4.7.1 daje mi to w linii zaznaczonej strzałką:
błąd: brak funkcji dopasowania dla wywołania 'S :: f (S &, const pass &)'
uwaga: kandydat to:
uwaga: szablon decltype ((f ((* this), t), void ())) S :: f (const T &)
uwaga: odrzucenie / zastąpienie argumentu szablonu nie powiodło się:
uwaga: kandydat oczekuje 1 argumentu, 2 podane
co najwyraźniej oznacza ten globalnyf
powyżej nie jest brany pod uwagę przy rozdzielczości przeciążenia.
Dlaczego tak jest i co mam zrobić, aby to zrobić?
Również dlaczego nie ma błędów w dwóch wierszach powyżej, gdzief
w decltype używane w podobny sposób?
AKTUALIZACJA
As @ n.m. powiedziano, funkcje składowe całkowicie pozbawione funkcji cienia, nawet jeśli ich podpisy są różne, więc tutaj jest obejście, które nie łamie ADL dlaf
(w przeciwieństwie do kwalifikacji pełnej nazwy sugerowanej przez @ n.m.). Wykonaj bezpłatną funkcję (f_dispatcher
) gdzieś nikt nie będzie wyglądał (detail
) i w pełni zakwalifikuj jego nazwę w środkuS::f
. W tej funkcji zadzwoń za darmof
i pozwól ADL zająć się tym stamtąd, tak:
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;
}