SFINAE -Попытка определить, имеет ли тип шаблона функцию-член с помощью & #39;variable& #39; возвращаемый тип

Проблемы с SFINAE. Мне нужно иметь возможность определить, имеет ли Type оператор функции-члена ->, определенный независимо от его возвращаемого типа. Пример следует.

Этот класс в тестере. Он определяет оператор -> ()с возвращаемым типом X *. Таким образом, я не буду знать, что такое «X», чтобы жестко закодировать его везде.

template <class X>
class PointerX
{
   ...

    X* operator->() const;
   ...
}

Этот класс пытается определить, имеет ли переданный в T оператор метода -> определенный; независимо от того, какой оператор -> возвращает тип.

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

Этот класс точно такой же, как и выше, за исключением того, что оператор -> возвращаемый тип должен быть «Объект».

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 «Оператор объекта -> ()const». Поэтому он использует общую версию Test Test (... ).

Однако HasOperatorMemberAccessorOBJECT смог найти PointX «Оператор объекта -> ()const». При этом используется специализированная версия Test Test(SFINAE*).

Оба должны были найти метод «Object operator -> ()const»; и поэтому оба должны использовать специализированную версию Test Test (SFINAE *); и, таким образом, значение HasOperatorMemberAccessor> ::должно быть истинным для обоих.

Единственная разница между HasOperatorMemberAccessor и HasOperatorMemberAccessorOBJECT заключается в том, что HasOperatorMemberAccessorOBJECT имеет имя типа R, жестко запрограммированное для объекта,

Таким образом, проблема заключается в том, что «decltype (GetReturnType (&U ::оператор -> ))" не возвращает Object правильно. Я пробовал несколько различных разрешений на обнаружение возвращаемого типа. Они идут следующим образом:

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

Ничего не работает, почему? Я использую MSVC++ 10.0.

5
задан ildjarn 26 April 2012 в 21:28
поделиться