c++ - `constexpr` 函数可以在 C++ 中前向声明吗?
问题描述
我可以constexpr
在给出定义之前在 C++ 中声明一个函数吗?
考虑一个例子:
constexpr int foo(int);
constexpr int bar() { return foo(42); }
constexpr int foo(int) { return 1; }
static_assert(bar() == 1);
它实际上是所有编译器都支持的,demo:https ://gcc.godbolt.org/z/o4PThejso
但是,如果foo
在模板中转换函数:
constexpr int foo(auto);
constexpr int bar() { return foo(42); }
constexpr int foo(auto) { return 1; }
static_assert(bar() == 1);
然后 Clang 拒绝接受它,说https://gcc.godbolt.org/z/EG7cG9KTM:
<source>:5:15: error: static_assert expression is not an integral constant expression
static_assert(bar() == 1);
^~~~~~~~~~
<source>:2:30: note: undefined function 'foo<int>' cannot be used in a constant expression
constexpr int bar() { return foo(42); }
^
<source>:5:15: note: in call to 'bar()'
static_assert(bar() == 1);
它仍然是有效的 C++ 代码还是 Clang 错误?
解决方案
这是核心问题2166。
第7.7 节 [expr.const] 状态:起草 提交人:Howard Hinnant 日期:2015-08-05
根据 7.7 [expr.const] bullet 2.3,表达式是常量表达式,除非(除其他原因外)它会计算
调用未定义的 constexpr 函数或未定义的 constexpr 构造函数;
这没有解决必须定义 constexpr 函数的点的问题。为了允许相互递归的 constexpr 函数,其目的是必须在最终导致调用的最外层评估之前定义该函数,但这没有明确说明。
换句话说,标准在这种情况下并不清楚,所以每个编译器都可以自由地接受或拒绝它认为合适的代码。
在 Clang 的情况下,auto
通过将函数转换为模板来实现参数。这使得编译器更难维护 constexpr 上下文。这并不是说不可能实现(毕竟 GCC 没有问题),直到 2166 解决它才不是 bug。
同时,您可以通过制作bar()
模板或auto
从foo()
.
推荐阅读
- typescript - 按属性类型提取值
- android - ionic cordova build --prod --release 失败并产生错误
- docker - 无法从保存的 tar 映像加载 docker
- google-apps-script - 用表格替换搜索文本
- typescript - 如何让我的 Ionic 4 Typescript 路径正常工作?
- ruby-on-rails - Rails - 单面参考的“无法写入未知属性”
- json - 添加 JSON 数据对象时接收警报
- javascript - D3 Choropleth:TypeError:无法读取未定义的属性“县”
- c++ - 使用 CRTP 创建特征矩阵
- c++ - 如何修复此错误“错误:没有匹配函数调用 'getline(std::ifstream&, st::_cx11::string&,