SFINAE - Es wird versucht festzustellen, ob der Vorlagentyp eine Elementfunktion mit dem Rückgabetyp 'Variable' hat

Probleme mit SFINAE. Ich muss in der Lage sein zu bestimmen, ob für einen Typ ein Elementfunktionsoperator definiert ist -> unabhängig von seinem Rückgabetyp. Beispiel folgt.

Diese Klasse im Tester. Es definiert den Operator -> () mit dem Rückgabetyp X *. Ich werde also nicht wissen, was "X" ist, um es überall fest zu codieren.

<code>template <class X>
class PointerX
{
    ...

    X* operator->() const;
    ...
}
</code>

Diese Klasse versucht festzustellen, ob für das übergebene T eine Methode operator-> defined ist. unabhängig vom Operator-> Rückgabetyp.

<code>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);
};
</code>

Diese Klasse ist die gleiche wie oben, außer dass operator-> return type 'Object' sein muss.

<code>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);
};
</code>

Ergebnisse:

<code>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<>*)  
}
</code>

HasOperatorMemberAccessor konnte die PointX-Mitgliedsfunktion "Object operator -> () const" nicht finden. Daher wird die generische Version von Test (...) verwendet.

HasOperatorMemberAccessorOBJECT konnte jedoch PointXs "Objektoperator -> () const" finden. Daher wird der Test der spezialisierten Version (SFINAE *) verwendet.

Beide hätten die Methode "Objektoperator -> () const" finden sollen; und daher sollten beide die spezialisierte Testversion (SFINAE *) von Test verwenden; und daher sollte HasOperatorMemberAccessor> :: value für beide zutreffen.

Der einzige Unterschied zwischen HasOperatorMemberAccessor und HasOperatorMemberAccessorOBJECT besteht darin, dass HasOperatorMemberAccessorOBJECT den Typnamen R hat, der fest mit dem Objekt verknüpft ist.

Das Problem ist also, dass "decltype (GetReturnType (& U :: operator->))" Object nicht korrekt zurückgibt. Ich habe verschiedene Möglichkeiten ausprobiert, um den Rückgabetyp zu ermitteln. Sie gehen wie folgt vor:

<code>    decltype( GetReturnType(&U::operator->) )
    typename decltype( GetReturnType(&U::operator->))
    decltype( ((U*)nullptr)->operator->() )
    typename decltype( ((U*)nullptr)->operator->() )
</code>

Keine Arbeit, warum? Ich verwende MSVC ++ 10.0.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage