2011-01-26 12 views
6

¿Existe alguna manera, mediante SFINAE, para detectar si una función libre está sobrecargada para una clase determinada?SFINAE: detectar si la clase tiene la función libre

Básicamente, tengo la siguiente solución:

struct has_no_f { }; 

struct has_f { }; 

void f(has_f const& x) { } 

template <typename T> 
enable_if<has_function<T, f>::value, int>::type call(T const&) { 
    std::cout << "has f" << std::endl; 
} 

template <typename T> 
disable_if<has_function<T, f>::value, int>::type call(T const&) { 
    std::cout << "has no f" << std::endl; 
} 

int main() { 
    call(has_no_f()); // "has no f" 
    call(has_f()); // "has f" 
} 

Simplemente sobrecarga call no funciona ya que en realidad hay una gran cantidad de foo y bar tipos y la función call no tiene conocimiento de ellos (básicamente call está dentro de a y los usuarios suministran sus propios tipos).

No puedo usar C++ 0x, y necesito una solución de trabajo para todos los compiladores modernos.

Lamentablemente, la solución a un similar question no funciona aquí.

+0

problema muy inetersting. También quiero saber la solución. –

+0

¿Desea detectar funciones que solo son visibles en el momento de creación de instancias? –

+0

@Johannes Realmente no importa en mi caso. En el momento de la instanciación (de la plantilla de función), todas las funciones candidatas * serán * conocidas. –

Respuesta

3
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <utility> 
#include <functional> 
#include <type_traits> 

struct X {}; 
struct Y {}; 

__int8 f(X x) { return 0; } 
__int16 f(...) { return 0; } 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) { 
    std::cout << "In call with f available"; 
    f(t); 
    return 0; 
} 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) { 
    std::cout << "In call without f available"; 
    return 0; 
} 

int main() { 
    Y y; X x; 
    call(y); 
    call(x); 
} 

Una modificación rápida de los tipos de retorno de f() produce la solución SFINAE tradicional.

+0

Creo que las sobrecargas de 'f' son las que deben detectarse, no son parte de la solución. – aschepler

3

Si se permite boost, el siguiente código podría cumplir su propósito:

#include <boost/type_traits.hpp> 
#include <boost/utility/enable_if.hpp> 
using namespace boost; 

// user code 
struct A {}; 
static void f(A const&) {} 
struct B {}; 


// code for has_f 
static void f(...); // this function has to be a free standing one 

template< class T > 
struct has_f { 
    template< class U > 
    static char deduce(U(&)(T const&)); 

    template< class U, class V > 
    static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type 
    deduce(U(&)(V const&)); 

    static char (&deduce(...))[2]; 

    static bool const value = (1 == sizeof deduce(f)); 
}; 

int main() 
{ 
    cout<< has_f<A>::value <<endl; 
    cout<< has_f<B>::value <<endl; 
} 

Sin embargo, existen restricciones severas.
El código asume que todas las funciones de usuario tienen la firma (T const&), , por lo que (T) no está permitido.
La función void f(...) en lo anterior parece necesitar ser una función independiente .
Si el compilador aplica la búsqueda de dos fases como se esperaba normalmente, probablemente todas las funciones del usuario deben aparecer antes de la definición de la plantilla has_f de clase .
Honestamente, no estoy seguro de la utilidad del código, pero de todos modos espero que esto ayude.

Cuestiones relacionadas