【发布时间】:2019-08-22 02:37:10
【问题描述】:
我遇到了一个只能在 gcc 上重现的编译器错误,我将它缩小到一个最小的可重现样本,该样本在 msvc 上也失败了,但仍然可以用 clang 编译。代码如下:
结构体 { 浮动_x[2]; constexpr float operator[](int index) const { return _x[index]; } float& 运算符[](int index) { return _x[index]; } }; 结构垫 { vec _x[2]; constexpr vec operator[](int index) const { return _x[index]; } vec& operator[](int index) { return _x[index]; } }; constexpr 浮动条(浮动 f) { 返回 f; } constexpr float one(mat const& m) { 返回 m[0][0]; // 在 gcc 5+、msvc 中失败 } constexpr float 2(mat const& m) { 返回条(m[0][0]); // 在 gcc 5+ 中失败 }据我所知,第 24 行 vec::operator[] 的重载决议不考虑 const 重载(第 5 行),因为 mat::operator[] const(第 13 行)按值返回,而不是按 const参考,但我不确定为什么会阻止考虑 vec::operator[] const。来自 gcc 的错误消息:
:在函数'constexpr float one(const mat&)'中: :24:18: 错误: 调用非 constexpr 函数'float& vec::operator[](int)' 返回 m[0][0]; // 在 gcc 5+、msvc 中失败来自 msvc:
(22): 错误 C3615: constexpr 函数 'one' 不能产生常量表达式 (24): 注意:失败是由于调用未定义的函数或未声明的 'constexpr' (24): 注意:见'vec::operator []'的用法原始代码在 msvc 中编译得很好,但示例没有,所以我花了一点时间才找到允许它与 msvc 一起工作的原因。显然,通过另一个 constexpr 函数传递返回值以某种方式迫使 msvc 考虑 const 重载,但我不知道这是什么原因。这是一个错误还是一些深奥的语言规则的结果?哪个编译器是正确的?
这里的最后一个问题是,这只是一个问题,因为 const 重载按值返回,如果它们按 const 引用返回,则任何编译器都没有错误。在这里按值返回是我应该消除的无用悲观吗?
【问题讨论】:
标签: c++