C++ 直接从指针强制转换到模板函数?

C++ 直接从指针强制转换到模板函数?,c++,visual-c++,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&l

我试图获取指向函数模板实例的指针,并将其强制转换为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
}
为什么会这样?函数
templateFunction
(对于具体类型
T=int
)未重载。可以推断我引用的函数的哪个实例

如果我将埃罗纽斯线替换为:

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

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

< P>两者都是技术上的错误:在C++中,不能将函数指针转换成<代码> Value*/Cuff> 指向函数类型的指针(如
void(*)(此处为int*)
与指向对象类型的指针(如
void*
此处)是完全不同的类型类别

VisualC++允许转换(例如在<代码> VATU*ADDR1=和PrimeStudio.<代码> >中是语言扩展(用<代码>/ZA FLAG编译,它禁用语言扩展,导致两行都被拒绝)。


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

编译器在这两种情况下都应该生成错误。根据标准§4.10/2,函数指针不能转换为
void
*,因为函数不是对象(§1.8/1)。VisualStudio2008允许将其作为扩展,请检查

使用
typedef
避免误解:

typedef void(func)(int*); // declare func type
func* addr1 = &plainFunction;         // OK
func* addr2 = &templateFunction<int>; // OK
typedef void(func)(int*);//声明func类型
func*addr1=&plainFunction;//好啊
func*addr2=&templateFunction;//好啊

您是对的,尽管函数指针通常可以转换为普通函数。更正问题以符合标准。@CygnusX1:我不确定我是否理解你的评论。正如您所演示的,VisualC++允许您将函数模板实例化的地址分配给函数指针。因为我的意思是“您是对的,虽然函数指针通常可以被转换成普通指针”。是我的错。很抱歉我想一件事,写另一件事。关于您的更新,指向函数的指针和指向对象的指针是否具有相同的大小和表示形式并不重要:根本不允许从函数指针转换到
void*
。请注意,在更新时,您不能通过
void(*)(
)调用这两个函数中的任何一个,因为这不是这两个函数的类型;您必须将
addr1
addr2
转换回正确的类型(
void(*)(int*)
)才能进行调用,否则行为未定义。我真正需要的是一个“函数入口点”,它稍后会传递到CUDA库。这个函数,实际上是指针指向的,它从来没有作为CPU可执行代码块存在过,它驻留在GPU上。我只是脱掉CUDA特定的东西,让我的例子尽可能简单,并从那些与C++工作的人那里得到一些输入,但不一定需要使用CUDA。我这样做并没有错——你的回答让我看到了我不知道的函数指针,尽管我已经多次使用它们。谢谢。所以你说,铸造到
void*
是违反标准的,而不仅仅是因为它“不必,但可以”?“不可转换”意味着标准禁止这样做。VS2008不是符合标准的编译器。如果你想保持代码的可移植性,就不应该在VS2008中使用这个bug。我不知道它实际上是个bug。现在我知道了。非常感谢。
void (*addr1)()=(void(*)())&plainFunction;
void (*addr2)()=(void(*)())(&templateFunction<int>);
typedef void(func)(int*); // declare func type
func* addr1 = &plainFunction;         // OK
func* addr2 = &templateFunction<int>; // OK