2

これが 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;
}
4

1 に答える 1

7

これは、SFINAE やテンプレート、C++11 や ADL とは関係ありません。

メンバーは、タイプに関係なく、同じ名前を持つすべての非メンバーをシャドウします。という名前のメンバーがある場合、修飾名 (例: ) を使用しない限り、fという名前の非メンバーを参照することはできません。f::f

を使用するだけ::f(*this, t);です。

于 2012-07-27T20:24:21.057 に答える