【问题标题】:VC++ error when using a pointer to a template function使用指向模板函数的指针时出现 VC++ 错误
【发布时间】:2011-09-03 05:59:21
【问题描述】:

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

模板回调.cpp(27):错误 C2664:'curl_easy_setopt':不能 从 'size_t 转换参数 3 (__cdecl *)(void *,size_t,size_t,void *)' 到 '...' 上下文不允许消除重载函数的歧义

但是 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++ 中的错误还是我做错了什么?

【问题讨论】:

  • @Pablo: 这是curl_easy_setopt 的确切签名吗?我想知道问题是否不是来自可变参数。
  • @Matthieu:问题确实来自可变参数。
  • @Xeo:你知道为什么,gcc-4.3.4 也拒绝代码,但 gcc-4.5.1 在 C++0x 模式下接受它。我一般不使用可变参数,所以我对问题的根源有点茫然:/
  • @Matthieu:对不起,不知道。 ://
  • @Matthieu M. 这几乎是完全一致的签名,除了被修剪以使其在没有依赖关系的情况下编译。

标签: c++ templates visual-c++ function-pointers


【解决方案1】:

我已经在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
}

问题似乎来自可变参数和函数指针的交互。

注意:在 C++0x 模式下使用 gcc-4.5.1 it works fine

我推测问题出在bar(或在您的情况下为curl_easy_setopt)的过载解决方案。

问题是,为了使用省略号,编译器决定如何传递参数:intdoublepointer,...似乎无法决定,通过本身,&amp;callback&lt;int&gt; 的类型是什么。

当我们使用foo,或者进行强制转换时,它是明确的,因为别无选择。

我怀疑存在转换问题,但我没有可深入研究的 C++03 标准版本。

【讨论】:

  • Clang 是唯一能正确接受 bool b = &amp;callback&lt;int&gt;; 的编译器,据我所知 :)
  • @Johannes:啊!太好了,你在这里!你能解释一下到底发生了什么吗?
  • @Matthieu 它应该根据 FDIS 规范接受这一点,就像 v4.5 一样。请参阅 llvm.org/bugs/show_bug.cgi?id=7505llvm.org/bugs/show_bug.cgi?id=9208 。 IIRC 在 C++03 中可能存在不允许这样做的问题(即仅基于模板参数识别正确的函数左值,没有正确的目标类型上下文)。请参阅所提及的 PR。
  • @Johannes FDIS 规范是什么?谷歌搜索没有帮助
  • @Pablo:FDIS 代表最终草案 ISO 标准。这是 C++ ISO 标准实际发布之前草案的最后一次改进(在 FDIS 得到所有国家 ISO 机构的审查之后)。它曾经可供下载,但他们似乎已将其删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 2013-02-19
  • 1970-01-01
  • 2016-10-18
相关资源
最近更新 更多