2011-05-27 10 views
7

Estoy intentando escribir una función de devolución de llamada de plantilla para libcurl. Sin embargo, cuando se utiliza un puntero a una instancia de la función de plantilla, VC++ 2008 y 2010 keep me da este error:Error de VC++ al usar un puntero a una función de plantilla

template-callback.cpp(27) : error C2664: 'curl_easy_setopt' : cannot convert parameter 3 from 'size_t (__cdecl *)(void *,size_t,size_t,void *)' to '...' Context does not allow for disambiguation of overloaded function

Pero GCC (4.5.1) compila el código sin ningún problema. Esta es una versión recortada del código:

#include <string> 

template<typename String> 
size_t callback(
    void*  ptr 
    , size_t size 
    , size_t nmemb 
    , void*  userdata 
) 
{ 
    //String* str = static_cast<String*>(userdata); 
    size_t len = size*nmemb; 
    //str->append(static_cast<char const*>(ptr), len); 
    return len; 
} 

typedef size_t (*write_callback)(void*, size_t, size_t, void*); 
struct CURL; 
enum CURLOption { none }; 
void curl_easy_setopt(CURL*, CURLOption, ...); 

void f() 
{ 
    CURL* curl = NULL; 
    CURLOption option = none; 

    // This gives an error 
    curl_easy_setopt(curl, option, &callback<std::string>); 

    // This doesn't 
    write_callback cb = &callback<std::string>; 
    curl_easy_setopt(curl, option, cb); 
} 

Es esto un error en VC++ o estoy haciendo algo mal?

+0

@Pablo: ¿es esta la firma exacta de 'curl_easy_setopt'? Me pregunto si el problema no proviene del argumento variado. –

+0

@ Matthieu: El problema proviene del argumento variadico. – Xeo

+0

@Xeo: ¿tienes alguna idea de por qué, gcc-4.3.4 también rechaza el código, pero gcc-4.5.1 lo acepta en modo C++ 0x. No uso argumentos variados en general, así que estoy un poco perdido en cuanto al origen del problema:/ –

Respuesta

1

He reproducido el problema en ideone (C++ 03 con gcc-4.3.4):

#include <iostream> 

typedef void (*FuncType)(int); 

void foo(FuncType); 
void bar(...); 

template <typename T> 
void callback(T t) { std::cout << t << "\n"; } 

int main() { 
    foo(&callback<int>); // OK 
    bar(static_cast<FuncType>(&callback<int>)); // OK 
    bar(&callback<int>); // error: address of overloaded function 
         // with no contextual type information 
} 

El problema parece venir de la interacción del argumento variadic y el puntero de función.

Nota: en el modo C++ 0x con gcc-4.5.1 it works fine

que suponer que el problema viene de la resolución de la sobrecarga de bar (o curl_easy_setopt en su caso).

El problema es que con el fin de utilizar los puntos suspensivos, el compilador como para decidir cómo pasar el argumento: int, double, pointer, ... parece que es incapaz de decidir, por sí mismo, lo que el tipo de &callback<int> es.

Cuando usamos foo, o realizamos un molde, no es ambiguo porque no hay otra opción.

Sospecho que hay un problema de conversión, pero no tengo una versión del estándar C++ 03 para profundizar.

+0

Clang es el único compilador que acepta 'bool b = & callback ;' correctamente, por lo que puedo ver :) –

+1

@Johannes: ¡ah! genial que estés aquí! ¿Podrías explicar exactamente qué está pasando? –

+0

@Matthieu Aceptará que según las especificaciones de FDIS, como v4.5 sí lo hace. Consulte http://llvm.org/bugs/show_bug.cgi?id=7505 y http://llvm.org/bugs/show_bug.cgi?id=9208. IIRC puede haber un problema en C++ 03 que no permitió esto (es decir, identificar la función correcta lvalor únicamente en función de argumentos de plantilla, sin un contexto de tipo de destino correcto). Por favor, consulte las RR.PP. referidas. –

Cuestiones relacionadas