能否从C++模块导出constexpr函数指针?Visual Studio编译报错技术问询
你的代码完全符合C++标准,问题出在Visual Studio编译器本身
首先可以肯定:你写的代码没有违反任何C++标准规则,出现内部编译器错误(ICE)是Visual Studio 16.9.0 Preview 4.0版本的编译器bug,而非你的代码有问题。
为什么你的代码是合法的?
我们拆解来看:
- constexpr函数指针的初始化:
twice是一个constexpr函数,根据C++标准,constexpr函数的地址属于常量表达式,完全可以用来初始化另一个constexpr变量——也就是你的func函数指针,这一步是完全合规的。 - 模块导出constexpr变量:C20模块允许导出constexpr变量,因为constexpr变量从C17起就默认是
inline的,而模块导出inline变量是标准明确允许的行为。你的func位于export namespace my中,相当于直接导出了这个constexpr函数指针,完全符合模块的导出规则。
为什么去掉第二个constexpr就能编译?
当你去掉func的constexpr修饰后,它变成了一个普通的函数指针变量。此时虽然严格来说,模块导出非inline变量需要显式加上inline关键字(否则不符合标准),但Visual Studio可能在这个场景下做了宽松处理,或者刚好绕过了触发ICE的编译器代码路径,所以代码能正常编译运行。但这并不代表你的原constexpr写法有问题——恰恰相反,原写法才是更符合C++标准意图的写法。
解决建议
- 优先尝试升级到Visual Studio的更高版本(比如后续的正式版或更新的预览版),这类编译器内部错误通常会在后续版本中被修复。
- 如果暂时无法升级,可以先使用去掉constexpr的临时方案,但记得如果要符合标准,应该给这个普通变量加上
inline修饰:export namespace my { inline int (*func)(int) = &twice; }
内容的提问来源于stack exchange,提问作者EPLKleijntjens
相关产品推荐
相关产品推荐

