2011-05-27 63 views
7

我正在尝试为libcurl编写模板回调函数。但是,使用指针模板函数的一个实例,VC++ 2008和2010年继续给我这个错误时:使用指向模板函数的指针时出现VC++错误

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

但是GCC(4.5.1)编译没有问题的代码。这是一个修剪版本的代码:

#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); 
} 

这是VC++中的错误还是我做错了什么?

+0

@Pablo:这是'curl_easy_setopt'的确切签名吗?我想知道这个问题是不是来自可变参数。 – 2011-05-27 09:18:00

+0

@Matthieu:问题确实来自可变参数。 – Xeo 2011-05-27 09:21:40

+0

@Xeo:你有什么想法为什么,gcc-4.3.4也会拒绝代码,但gcc-4.5.1在C++ 0x模式下接受它。我一般不会使用可变参数,所以我对这个问题的起源有点遗憾:/ – 2011-05-27 09:30:20

回答

1

我已复制了问题的ideone(C++ 03用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 
} 

这个问题似乎来自一个可变参数的相互作用和函数指针。

注:C++ 0x中模式GCC-4.5.1 it works fine

我猜测,这个问题来自于bar重载解析(或curl_easy_setopt你的情况)。

的问题是,为了使用省略号,编译器,以决定如何传递参数:intdoublepointer ...这似乎是无法决定,其本身是什么类型&callback<int>是。

当我们使用foo或执行演员时,它是明确的,因为没有选择。

我怀疑是一个转换问题,但我没有一个C++ 03标准的版本来挖掘。

+0

Clang是唯一一个接受'bool b =&callback ;'正确地,从我能看到的:)编译器:) – 2011-05-27 09:42:59

+1

@Johannes:啊!太棒了,你在这里!你能解释一下到底发生了什么? – 2011-05-27 09:46:51

+0

@Matthieu它应该接受根据FDIS规范,像v4.5一样。请参阅http://llvm.org/bugs/show_bug.cgi?id=7505和http://llvm.org/bugs/show_bug.cgi?id=9208。 IIRC在C++ 03中可能存在一个不允许的问题(即仅仅根据模板参数识别正确的函数左值,而没有正确的目标类型上下文)。请参阅提及的PR。 – 2011-05-27 09:53:40