2011-05-27 62 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