Tiene 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.SFINAE - Tratando de determinar si el tipo de plantilla tiene función de miembro con el tipo de devolución 'variable'
Esta clase en el probador. Define operador ->() con un tipo de retorno de X *. Por lo tanto, no sabré qué 'X' es codificarlo en todos lados.
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
Esta clase intenta determinar si el pasado en T tiene un método operator-> defined; independientemente de qué operador-> tipo de retorno sea.
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);
};
Esta clase es exactamente la misma que la anterior, excepto que operator-> return type tiene que ser '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);
};
Resultados:
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 fue incapaz de encontrar la función miembro de pointx "operador de objetos ->() const". Entonces usa la versión genérica Test (...) de Test.
Sin embargo, HasOperatorMemberAccessorOBJECT pudo encontrar "Object operator ->() const" de PointX. Por lo tanto, utiliza Prueba de prueba versión especializada (SFINAE *).
Ambos deberían haber encontrado el método "Object operator ->() const"; y, por lo tanto, ambos deberían usar la versión especializada Test de Test (SFINAE *); y así HasOperatorMemberAccessor> :: value debería ser verdadero para ambos.
La única diferencia entre HasOperatorMemberAccessor y HasOperatorMemberAccessorOBJECT es que HasOperatorMemberAccessorOBJECT tiene el nombre de tipo R hardcoded a oponerse,
Así que la cuestión es que "decltype (GetReturnType (& T :: del operador>))" no está regresando de objetos correctamente. He intentado varias posibilidades diferentes de descubrir el tipo de devolución. Van de la siguiente manera:
decltype(GetReturnType(&U::operator->))
typename decltype(GetReturnType(&U::operator->))
decltype(((U*)nullptr)->operator->())
typename decltype(((U*)nullptr)->operator->())
Ninguno funciona, ¿por qué? Estoy usando MSVC++ 10.0.
Una cosa que llama la atención es que 'PointerX :: operator->' devuelve 'bool *', no 'bool'. –
El tipo de X en PointerX no importa en lo que se refiere a HasOperatorMemberAccessor. Traté de generalizar mi problema al no agregar muchos objetos extraños al ejemplo. Si es demasiado confuso, cambiaré bool a cadena. –
Déjame intentarlo de nuevo. 'PointerX