I'm trying to write a template callback function for libcurl. However, when using a pointer to an instance of the template function, VC++ 2008 and 2010 keep giving me this error:
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
But GCC (4.5.1) compiles the code without a problem. This is a trimmed version of the code:
#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);
}
Is this a bug in VC++ or am I doing something wrong?
I have reproduced the issue on ideone (C++03 with 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
}
The issue seems to come from the interaction of the variadic argument and the function pointer.
Note: in C++0x mode with gcc-4.5.1 it works fine
I surmise that the issue comes from the overload resolution of bar
(or curl_easy_setopt
in your case).
The problem is that in order to use the ellipsis, the compiler as to decide how to pass the argument: int
, double
, pointer
, ... It seems that it is unable to decide, by itself, what the type of &callback<int>
is.
When we use foo
, or perform a cast, it is unambiguous because there is no choice.
I suspect a conversion issue, but I don't have a version of the C++03 standard to dig into.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With