7

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?

7
  • @Pablo: is this the exact signature of curl_easy_setopt ? I am wondering if the issue does not come from the variadic argument. Commented May 27, 2011 at 9:18
  • @Matthieu: The problem does indeed come from the variadic argument. Commented May 27, 2011 at 9:21
  • @Xeo: do you have any idea why, gcc-4.3.4 rejects the code too, but gcc-4.5.1 accepts it in C++0x mode. I don't use variadic arguments in general so I am a bit at a loss as to the origin of the issue :/ Commented May 27, 2011 at 9:30
  • @Matthieu: Sorry, no clue. :/ Commented May 27, 2011 at 9:31
  • @Matthieu M. It is almost the exact signature, except trimmed down to make it compile without dependencies. Commented May 27, 2011 at 17:26

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Clang is the only compiler that accepts bool b = &callback<int>; correctly, from what I can see :)
@Johannes: ah! great that you're here! Could you explain exactly what's going on ?
@Matthieu It shall accept that according to the FDIS specs, like v4.5 does. See llvm.org/bugs/show_bug.cgi?id=7505 and llvm.org/bugs/show_bug.cgi?id=9208 . IIRC there may be an issue in C++03 that didn't allow this (i.e identifying the correct function lvalue solely based on template arguments, without a correct target type context). Please see the referred-to PRs.
@Johannes what are the FDIS specs? Googling doesn't help
@Pablo: FDIS stands for Final Draft ISO Standard. It's the last refinement of the drafts before the C++ ISO Standard is actually published (after the FDIS gets vetted by all National ISO bodies). It used to be available for download, but they seem to have removed it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.