これが sfinae と関係があるのか 、それともテンプレート化された関数に関連するものなのかはわかりません。sfinae を使用して、対応するフリー関数の存在に基づいてメンバー関数を有効/無効にしようとしています。これは、別の型のメンバー関数の存在に基づいて有効/無効にされます。ここで説明するすべての方法を使用します。
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;
}
ただし、gcc 4.7.1 では、矢印でマークされた行に次のように表示されます。
エラー: 'S::f(S&, const pass&)' の呼び出しに一致する関数がありません
注: 候補は:
注: テンプレート decltype ((f((* this), t), void())) S::f (const T&)
注: テンプレート引数の演繹/代入に失敗しました:
注: 候補者は 1 つの引数を期待し、2 つの引数が提供されることを期待しています
これは明らかに、f
上記のグローバルがオーバーロードの解決には考慮されていないことを意味します。
それはなぜですか、そうするために私は何をしますか?
f
また、同様の方法で decltypeで使用されている場合、2 行上にエラーがないのはなぜですか?
アップデート
@nm が言ったように、メンバー関数は署名が異なっていても完全に自由な関数をシャドーしf
ます。フリー関数 ( f_dispatcher
) を誰も見ない場所 ( detail
) に作成し、その名前を 内で完全に修飾しますS::f
。その関数で freef
を呼び出し、それ以降は ADL に処理させます。次のようにします。
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;
}