SFINAE によるメンバー関数検出の継承
SFINAE (置換失敗はエラーではありません) により、指定されたクラス内のメンバー関数の検出が可能になります。ただし、継承されたメンバー関数に適用すると、SFINAE に制限が発生し、誤検出が発生します。
この問題を説明するには、次のコードを考えてみましょう。
<code class="cpp">// Does not correctly detect inherited member functions template<typename T, typename Sig> struct has_foo { template <typename U, U> struct type_check; template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1]; template <typename > static char (& chk(...))[2]; static bool const value = (sizeof(chk<T>(0)) == 1); }; struct A { void foo(); }; struct B : A {}; int main() { using namespace std; cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true cout << boolalpha << has_foo<B, void (B::*)()>::value << endl; // false }
この例では、has_foo は失敗します。 A から B に継承された foo() メンバーを検出します。
この制限を克服するには、より洗練された SFINAE テクニックが必要です。次の解決策を考えてみましょう:
<code class="cpp">template <typename Type> class has_foo { class yes { char m;}; class no { yes m[2];}; struct BaseMixin { void foo(){} }; struct Base : public Type, public BaseMixin {}; template <typename T, T t> class Helper{}; template <typename U> static no deduce(U*, Helper<void (BaseMixin::*)(), &U::foo>* = 0); static yes deduce(...); public: static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0))); }; // Usage struct A { void foo(); }; struct B : A {}; struct C {}; int main() { using namespace std; cout << boolalpha << has_foo<A>::result << endl; cout << boolalpha << has_foo<B>::result << endl; cout << boolalpha << has_foo<C>::result; }</code>
結果:
true true false
この解決策では、foo() メンバー関数を提供する基本ミックスイン クラス BaseMixin が導入されます。継承されたメンバー関数は、ミックスイン クラス内の foo() の存在をチェックすることで検出されます。この手法により、複数のレベルで継承されたメンバー関数を含む、継承されたメンバー関数を正確に検出できます。
以上がSFINAE が継承されたメンバー関数を検出できないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。