SFINAE - Intentando determinar si el tipo de plantilla tiene función miembro con el tipo de retorno 'variable'

Teniendo problemas con SFINAE. Necesito poder determinar si un Tipo tiene un operador de función miembro-> definido independientemente de su tipo de devolución. El ejemplo sigue.

Esta clase en el probador. Define operador -> () con un tipo de retorno de X *. Por lo tanto, no sabré qué es la 'X' para codificarla en todas partes.

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

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

Esta clase intenta determinar si el aprobado en T tiene un método operador-> definido; independientemente de qué operador-> tipo de retorno es.

<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>

Esta clase es exactamente la misma que la anterior, excepto que operador-> tipo de devolución debe ser 'Objeto'.

<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>

Resultados:

<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 no pudo encontrar la función miembro de PointX "Operador de objeto -> () const". Entonces usa la versión genérica de Test Test (...).

Sin embargo, HasOperatorMemberAccessorOBJECT pudo encontrar el "Operador de objetos -> () const de PointX". Por lo tanto, utiliza la versión Test Test especializada (SFINAE *).

Ambos deberían haber podido encontrar el método "Operador de objeto -> () const"; y, por lo tanto, ambos deben usar la versión especializada de Test Test (SFINAE *); y, por lo tanto, HasOperatorMemberAccessor> :: value debe ser verdadero para ambos.

La única diferencia entre HasOperatorMemberAccessor y HasOperatorMemberAccessorOBJECT es que HasOperatorMemberAccessorOBJECT tiene el nombre de código R codificado para objetar,

Entonces, el problema es que "decltype (GetReturnType (& U :: operator->))" no está devolviendo el objeto correctamente. He intentado una serie de permisos diferentes para descubrir el tipo de retorno. Van de la siguiente manera:

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

Ninguno funciona, ¿por qué? Estoy usando MSVC ++ 10.0.

Respuestas a la pregunta(1)

Su respuesta a la pregunta