为何Clang不允许将模板函数地址static_cast为void*?
模板函数地址转void*的跨编译器差异
先看你给出的代码:
template<typename T> int prt(T a) { return ++a; } void* ptr = static_cast<void*>(&prt<int>);
这段代码在MSVC能正常编译,但Clang会抛出错误:
address of overloaded function 'prt' cannot be static_cast to type 'PVOID' (aka 'void *')
原因解析
- C++标准明确规定,函数指针和
void*之间不能用static_cast直接转换,这类操作属于未定义行为范畴。 - MSVC提供了非标准扩展,允许这种转换作为便利特性,但这是编译器特有的支持,不符合C++标准规范。
- Clang(包括GCC这类严格遵循标准的编译器)会直接拒绝该操作,因为它严格执行C++标准规则,避免引入未定义行为导致潜在的程序问题。
标准合规的替代方案
如果确实需要将函数指针转为void*,标准允许的方式是借助uintptr_t(需包含<cstdint>头文件)中转:
#include <cstdint> template<typename T> int prt(T a) { return ++a; } void* ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&prt<int>));
需要注意的是,标准并不保证所有平台上函数指针的大小都和uintptr_t匹配,只是在绝大多数主流平台上这种转换是可行的。
内容的提问来源于stack exchange,提问作者Barracudach
相关产品推荐
相关产品推荐

