SFINAE - Próba określenia, czy typ szablonu ma funkcję składową z typem powrotu „zmienna”

Problemy z SFINAE. Muszę być w stanie określić, czy typ ma operatora funkcji-zdefiniowanej niezależnie od typu zwracanego. Poniżej następuje przykład.

Ta klasa w testerze. Definiuje operator -> () z typem powrotu X *. Nie będę więc wiedział, gdzie „X” ma zakodować go wszędzie.

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

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

Ta klasa próbuje określić, czy przekazany w T ma zdefiniowany operator metody->; niezależnie od typu operatora-> powrotu.

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

Ta klasa jest dokładnie taka sama jak powyżej, z tym wyjątkiem, że typ operator-> return musi mieć wartość „Object”.

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

Wyniki:

<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 nie mógł znaleźć funkcji członka PointX „Operator obiektu -> () const”. Używa więc wersji testowej Test (...).

Jednak HasOperatorMemberAccessorOBJECT był w stanie znaleźć „operator obiektu -> () const”. W ten sposób wykorzystuje testową wersję specjalną Test (SFINAE *).

Obie powinny były w stanie znaleźć metodę „Operator obiektu -> () const”; i dlatego oba powinny używać Testowanej wersji testowej (SFINAE *); a zatem HasOperatorMemberAccessor> :: value powinno być prawdziwe dla obu.

Jedyną różnicą między HasOperatorMemberAccessor a HasOperatorMemberAccessorOBJECT jest to, że HasOperatorMemberAccessorOBJECT ma na stałe zakodowaną nazwę obiektu R,

Problem polega na tym, że „decltype (GetReturnType (& U :: operator->))” nie zwraca poprawnie obiektu. Próbowałem wielu różnych pozwoleń na odkrycie typu powrotu. Postępują w następujący sposób:

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

Nic nie działa, dlaczego? Używam MSVC ++ 10.0.

questionAnswers(1)

yourAnswerToTheQuestion