2010-05-18 10 views
9

No puedo entender por qué este segmento da error de función sobrecargada sin resolver (gcc versión 4.3.4 (Debian 4.3.4-6)):C++ función de refuerzo de la plantilla sobrecargada

#include <algorithm> 
#include <boost/function.hpp> 

// this does not work 
int main1() 
{ 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(&std::max<int>); 
} 

// this does not work 
int main2() { 
    typedef boost::function2<const int&, const int&, const int&> max; 
    max m(static_cast<max>(&std::max<int>)); 
} 

¿me pueden ayudar, gracias

test.cpp: In function âint main()â: 
test.cpp:7: error: no matching function for call to âboost::function2<const int&, const int&, const int&>::function2(<unresolved overloaded function type>)â 
/usr/include/boost/function/function_template.hpp:747: note: candidates are: boost::function2<R, T1, T2>::function2(const boost::function2<R, T1, T2>&) [with R = const int&, T0 = const int&\ 
, T1 = const int&] 
/usr/include/boost/function/function_template.hpp:739: note:     boost::function2<R, T1, T2>::function2(boost::function2<R, T1, T2>::clear_type*) [with R = const int&, T0 = cons\ 
t int&, T1 = const int&] 
/usr/include/boost/function/function_template.hpp:707: note:     boost::function2<R, T1, T2>::function2() [with R = const int&, T0 = const int&, T1 = const int&] 

máx/mín se define como

template<typename _Tp> 
    inline const _Tp& 
    max(const _Tp& __a, const _Tp& __b) 
    { 
     // concept requirements 
     __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) 
     //return __a < __b ? __b : __a; 
     if (__a < __b) 
     return __b; 
     return __a; 
    } 

he intentado todo tipo de plantilla de instancias explícita pero nothi ng parece funcionar. El mismo problema se presenta con g ++ 4.1 pero no con ICC

esto funciona

#include <algorithm> 
#include <boost/function.hpp> 

namespace std_ { 
    template<typename _Tp> 
    inline const _Tp& 
    max(const _Tp& __a, const _Tp& __b) 
    { 
     // concept requirements 
     //return __a < __b ? __b : __a; 
     if (__a < __b) 
      return __b; 
     return __a; 
    } 
} 

int main() 
{ 
    typedef const int &T; 
    typedef boost::function<T(T,T)> min_; 
    //typedef const int&(*min_)(const int&, const int&); 
    min_ m(::std_::max<int>); 
} 

y esto

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    //typedef const int &T; 
    //typedef boost::function<T(T,T)> min_; 
    typedef const int&(*min_)(const int&, const int&); 
    min_ m(::std::max<int>); 
} 
+0

¿Funciona sin el 'static_cast', o con la clase genérica' function'? – GManNickG

+0

@GMan no, no funciona sin conversión estática (eso era señal de desesperación). ¿Qué es la clase de función genérica? – Anycorn

+0

Lo que tienes. Quiero decir genérico simplemente como "no específico para un n específico". (Es decir, "función" es más genérica que "función2"). – GManNickG

Respuesta

6

Actualización: trata de un error de gcc que se ha fijado en gcc> = 4.4. bugzilla. Además, revisé mi respuesta con un caso de prueba reducido.

Existen dos componentes para este problema: la función boost :: function adopta un puntero a la función y el error gcc.

impulso :: función - Hay algo extraño en el mensaje de error enumerados en la pregunta; no hay ningún constructor candidato que acepte algo así como una dirección de función. Excavar en el src impulso :: función, el constructor relevante es (dejando de lado el argumento enable_if):

template<typename Functor> 
function(Functor f) : base_type(f) {} 

Así impulsar :: función no le ayuda en absoluto en la especificación del tipo de un puntero de función; si la función está sobrecargada, la dirección debe emitirse para especificar su tipo. Si se utiliza una dirección de función sobrecargada, la plantilla anterior no se puede crear una instancia y, por lo tanto, el constructor apropiado no aparece en el mensaje de error.

fallo gcc - Si nos fijamos en la cabecera stl_algobase.h de nuevo, verá que hay dos plantillas llamado Max, una versión de dos parámetro y una versión de un solo parámetro. Sin embargo, esto no debería ser un problema con tu código, ¿verdad? El término &max<int> debe crear una instancia de la versión de parámetro individual y tomar su dirección. Sin embargo, eso no es lo que sucede. Se puede ver el problema de la reducción (sin cabecera) de casos de prueba:

template <class T> 
const T& max(const T& x, const T& y){ 
    return x > y ? x : y; 
} 

template <class T, class C> 
const T& max(const T& x, const T& y, C comp){ 
    return comp(x, y) ? y : x; 

} 

template <class R, class A0, class A1> 
struct functor{ 
    template <class F> 
    functor(F f) : f(f) {} 
    R (*f)(A0, A1); 
}; 

int main(void){ 
    functor<const int&, const int&, const int&> func(&max<int>); 
    return 0; 
} 

Los anteriores resultados de código en un unresolved overloaded function type con gcc 4.3.4. La solución es eliminar la definición template <class T, class C> max(...){...} o agregar un static_cast<const int& (*)(const int&, const int&)>(...) alrededor de la dirección de la función. Supongo que el problema tiene que ver con la aplicación incorrecta de la especificación de parámetros explícitos parciales, que se especifica en el estándar. Le permite dejar de lado los parámetros de plantilla para hacer cosas como especificar un tipo de valor devuelto y no los tipos de argumento. Es decir, el compilador crea una instancia de ambas plantillas cuando solo debería crear una instancia de la plantilla completamente especificada. Sin embargo, es una especulación discutible, ya que el error se ha corregido en gcc> = 4.4.

Desde uno no debe cortar en stl_algobase.h;), el trabajo alrededor Vicente sugiere es el correcto, es decir, emitir el puntero de función a la función deseada puntero tipo const int& (*)(const int&, const int&). En tu código, el elenco no funciona porque, como señala GMan, estás transfiriendo a una función boost :: < ...>, que no hace nada para resolver la ambigüedad del puntero a la función.

5

Para criticar el código, no hay razón para que static_cast. Considere todo lo que el reparto va a hacer es usar el constructor de boost::function2 para hacer un nuevo boost::function2, luego será copiado en m. Sólo construir directamente en m:

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    typedef boost::function2<const int&, const int&, const int&> max; 
    max m(&std::max<int>); 
} 

Por último, la sintaxis preferida de boost::function es:

#include <algorithm> 
#include <boost/function.hpp> 

int main() 
{ 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(&std::max<int>); 
} 

Las clases específicas n-aria son para apoyo compilador más.

+0

mismo problema, lo he intentado antes. También probé un nuevo estilo (primero). Publiqué el error de compilación – Anycorn

+0

@aaa: Ya veo. Voy a hacer esta CW y luego dejar la crítica. Tal vez deberías publicar el mensaje de error real, no veo nada mal con tu código. – GManNickG

3

parece ser un problema con la definición de la función de plantilla std :: máximo con versiones de gcc 4.4 <

con gcc-4.4.0 y msvc Express9 funciona.

Los siguientes trabajos también para gcc-3.4 y gcc-4,3

int main1() 
{ 
    int res = std::max(1,2); 
    typedef boost::function<const int&(const int&, const int&)> max; 
    max m(static_cast<const int&(*)(const int&, const int&)>(std::max<int>)); 

    return 0 
} 
Cuestiones relacionadas