Having trouble with SFINAE. I need to be able to determine if a Type has a member function operator-> defined regardless of its return type. Example follows.
This class in the tester. It defines operator->() with a return type of X*. I thus will not know what 'X' is to hardcode it everywhere.
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
This class tries to determines if the passed in T has a method operator-> defined; regardless of what operator-> return type is.
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);
};
This class is the exact same as above except that operator-> return type has to be '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);
};
Results:
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 was unable to find PointX's member function "Object operator->() const". So it uses Test's generic version Test(...).
However, HasOperatorMemberAccessorOBJECT was able to find PointX's "Object operator->() const". Thus it uses Test specialized version Test(SFINAE*).
Both should have been able to find the "Object operator->() const" method; and thus both should use Test's specialized version Test(SFINAE*); and thus HasOperatorMemberAccessor>::value should be true for both.
The only difference between HasOperatorMemberAccessor and HasOperatorMemberAccessorOBJECT is that HasOperatorMemberAccessorOBJECT has the typename R hardcoded to object,
So the issue is that "decltype( GetReturnType(&U::operator->))" is not returning Object correctly. I've tried a number of different permitations of discovering the return type. They go as follows:
decltype( GetReturnType(&U::operator->) )
typename decltype( GetReturnType(&U::operator->))
decltype( ((U*)nullptr)->operator->() )
typename decltype( ((U*)nullptr)->operator->() )
None work, why? I'm using MSVC++ 10.0.