静态constexpr指针指向函数,编译器之间的区别
static constexpr pointer-to-function, difference between compilers
在回答这个问题时,我用gcc(已编译的代码)和clang(已拒绝的代码)尝试了以下代码:
typedef long (*func)(int);
long function(int) { return 42; }
struct Test
{
static constexpr func f = &function;
};
template<func c>
struct Call
{
static void f()
{
c(0);
}
};
int main()
{
Call<Test::f>::f();
}
我不确定哪个编译器是正确的,虽然我认为Test::f
的constexpr初始化是可以的。clang输出的错误是:
error: non-type template argument for template parameter of pointer type 'func'
(aka 'long (*)(int)') must have its address taken
- 哪个编译器是正确的?
- 如果clang是正确的,为什么,这个错误到底意味着什么?
编辑:"为什么",看到多元印刷的问题。
14.3.2模板非类型参数[temp.arg.nontype]
非类型、非模板模板形参的模板实参必须是:
[…]
——一个常量表达式(5.19),用于指定具有静态存储> duration和外部或内部链接的对象的地址,或具有外部或内部链接的函数的地址,包括函数模板和函数模板id,但不包括非静态类成员,表示为(忽略括号)&id-expression,除了&引用函数或数组的可以省略,引用模板形参的可以省略;[…]
(n3485,重点是我的)
我不知道为什么它被限制,但我认为这可能与函数地址在编译时不可用的事实有关(可能有模板实例化目的的替代品)。
编辑:由于Synxis的后续问题(评论),增强了答案
constexpr func = &function;
^这是格式良好的;您可以使用函数的地址来初始化constexpr
对象。问题是,它明确禁止使用指针作为非类型模板参数,除了形式&identifier
:
using My_Call = Call < &function >; // fine
constexpr func mypointer = &function; // fine
using My_Ind_Call = Call < func >; // forbidden, argument not of form `&id`
相关文章:
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 编译器如何在前缀和 postix 运算符之间进行区分?
- 填充上编译器生成的复制构造函数之间的不一致
- 不同c++编译器之间的自动类型推导不匹配
- 如何让CMake在多个编译器之间进行选择?
- 这些编译器之间是否有任何区别
- Android NDK 中的预构建工具链和自定义工具链编译器之间的差异
- CL和G 编译器之间的差异
- 编译器之间在丢弃的 if constexpr(false) 语句中实例化模板的行为不一致
- 可视化 为什么这个C++程序在某些编译器中有效,而在其他编译器中不起作用?C ++编译器之间的主要区别是什么
- 编译器之间的 Qt DLL 兼容性
- 回答两个编译器之间的差异
- 模板类中的尾随返回类型(GNU和Microsoft编译器之间的矛盾)
- 在编译器之间读取和写入原始对象到磁盘(istream)
- 如何在makefile中的编译器之间切换
- 在不同编译器之间一致触发的警告
- 编译器之间的浮点二进制布局
- 静态constexpr指针指向函数,编译器之间的区别
- c++编译器之间的巨大性能差异
- 预处理器和编译器之间的边界到底在哪里?