2012-06-30 19 views
5

que tiene esta función de miembro de ensayo:SFINAE función miembro problema prueba de la existencia

template <typename T> 
struct has_member { 
    template <typename U> static true_type f(decltype(declval<U>().member()) *); 
    template <typename> static false_type f(...); 
    static const bool value = decltype(f<T>(0))::value; 
}; 

Evalúa a cierto cuando existe una función miembro con un nombre dado, en el caso de que la función tiene una sobrecarga que no toma argumentos. Para tales funciones y en el caso de los contenedores STL, funciona correctamente excepto para las funciones de acceso a elementos (frontal, posterior, etc.), donde invariablemente se evalúa como falso.

¿Por qué es eso? Tengo mingw g ++ 4.7.

+0

¿El tipo de cambio al final es útil? 'auto f (U * p) -> decltype (p-> member(), true_type());' – Xeo

Respuesta

6

Esto se debe a que estas funciones devuelven referencias, y está declarando un puntero al valor de retorno, que es un puntero a una referencia, y eso es imposible.

La solución rápida sería:

template <typename U> static true_type 
     f(typename remove_reference< decltype(declval<U>().member()) >::type *); 

PS: Este tipo de errores puede ser (relativamente) fácil de resolver si se fuerza el compilador para dar un error cuando el SFINAE falla y creo que no debería.

Es decir, en su código, solo comente el false_type y vea los errores del compilador cuando true_type es la única opción. Entre un grupo de líneas sin sentido, se encuentra lo siguiente:

test.cpp:9:50: error: forming pointer to reference type 
    ‘__gnu_cxx::__alloc_traits<std::allocator<int> >::value_type& {aka int&}’ 
+0

Gracias, eso funcionó. Creo que también descubrí una forma de hacerlo sin eliminar la referencia: incluyo "typename Check = decltype (declval () .front()" como segundo argumento de plantilla, y hago que f pase un puntero char en su lugar. –

+0

@ AndrásKovács - Aún mejor de esta manera. – rodrigo

Cuestiones relacionadas