SFINAEに問題があります。タイプに、その戻りタイプに関係なく、メンバー関数operator->が定義されているかどうかを判別できる必要があります。次に例を示します。
テスターのこのクラス。X *の戻り型でoperator->()を定義します。したがって、どこでもハードコーディングするための「X」が何であるかはわかりません。
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
このクラスは、渡されたTにメソッドoperator->が定義されているかどうかを判別しようとします。演算子->戻り値のタイプに関係なく。
template<typename T>
struct HasOperatorMemberAccessor
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, decltype( GetReturnType(&U::operator->)), &U::operator-> >*);
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
このクラスは、operator-> returntypeが'Object'でなければならないことを除いて、上記とまったく同じです。
template<typename T>
struct HasOperatorMemberAccessorOBJECT
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, Object*, &U::operator-> >*); // only change is we hardcoded Object as return type.
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
結果:
void main()
{
HasOperatorMemberAccessor<PointerX<Object>>::Test<PointerX<Object>>(0); // fails ::value is false; Test => Test(...)
HasOperatorMemberAccessorOBJECT<PointerX<Object>>::Test<PointerX<Object>>(0); // works! ::value is true; Test => Test(SFINAE<>*)
}
HasOperatorMemberAccessorは、PointXのメンバー関数「Objectoperator->()const」を見つけることができませんでした。したがって、Testの汎用バージョンTest(...)を使用します。
ただし、HasOperatorMemberAccessorOBJECTは、PointXの「オブジェクト演算子->()定数」を見つけることができました。したがって、Test専用バージョンTest(SFINAE *)を使用します。
どちらも「Objectoperator->()const」メソッドを見つけることができたはずです。したがって、両方ともTestの専用バージョンTest(SFINAE *)を使用する必要があります。したがって、HasOperatorMemberAccessor>::valueは両方に対してtrueである必要があります。
HasOperatorMemberAccessorとHasOperatorMemberAccessorOBJECTの唯一の違いは、HasOperatorMemberAccessorOBJECTのタイプ名Rがオブジェクトにハードコードされていることです。
したがって、問題は、「decltype(GetReturnType(&U :: operator->))」がオブジェクトを正しく返さないことです。私は、返品タイプを発見するためのさまざまな許可を試しました。彼らは次のように行きます:
decltype( GetReturnType(&U::operator->) )
typename decltype( GetReturnType(&U::operator->))
decltype( ((U*)nullptr)->operator->() )
typename decltype( ((U*)nullptr)->operator->() )
何も機能しません、なぜですか?MSVC++10.0を使用しています。