直接从指针转换为模板函数?

时间:2011-03-11 19:41:26

标签: c++ visual-c++

我正在尝试使用指向函数模板实例的指针并将其转换为void *:

#include <stdio.h>

void plainFunction(int *param) {}

template <typename T>
void templateFunction(T *param) {}

int main() {
    void *addr1=&plainFunction; //OK
    void *addr2=&templateFunction<int>; //Compile error
}

我收到以下错误(在Visual Studio 2008中)

main.cu(10) : error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(T *)' to 'void *'
Context does not allow for disambiguation of overloaded function

为什么会这样?函数templateFunction(对于具体类型T=int)不会重载。可以减去我所引用的函数的哪个实例。

如果我用以下代码替换erroneus行:

void (*foo)(int*)=&templateFunction<int>;
void *addr2=foo;

编译没有问题。

谢谢!


更新

当正常指针void*被虚拟函数指针void(*)()替换时,正如James(谢谢)建议的那样,它会使错误消失:

void (*addr1)()=(void(*)())&plainFunction;
void (*addr2)()=(void(*)())(&templateFunction<int>);

但是,如果错误是通过将函数指针转换为普通指针引起的,则编译器应该在两种情况下都抱怨。但它没有,所以我继续假设它至少对于这个编译器来说是正确的。如果我没有弄错,标准只是说函数指针不必像普通指针一样表示,但它并不禁止它。

2 个答案:

答案 0 :(得分:12)

两者在技术上都是错误的:在C ++中,您无法将函数指针转换为void*

指针到函数类型(如此处的void (*)(int*))是一种完全不同的类型,而不是指向对象的类型(如此处的void*)。

允许转换的Visual C ++(例如在void* addr1 = &plainFunction;中)是一种语言扩展(使用/Za标志进行编译,禁用语言扩展,导致两行都被拒绝。)

错误有点误导,当然,虽然其他一些编译器同样没有帮助(Comeau报告“错误:没有函数模板实例”templateFunction“匹配所需的类型”)。

答案 1 :(得分:6)

编译器应该在两种情况下都会产生错误。由于函数不是对象(§1.8/ 1),因此函数指针不能根据标准§4.10/ 2转换为void *。 Visual Studio 2008允许将其作为扩展名,检查this bug

使用typedef以避免误解:

typedef void(func)(int*); // declare func type
func* addr1 = &plainFunction;         // OK
func* addr2 = &templateFunction<int>; // OK
相关问题