本地 constexpr 变量引入编译器错误
local constexpr variable introduces compiler error
除非您将标记为 ok 的行替换为标记为 fails 的行,否则以下代码将按预期编译和工作。唯一的区别是我正在创建一个本地临时 constexpr 变量。我不明白为什么它只在一种情况下失败。
#include <array>
using TArray = std::array<int, 2>;
using TSize = TArray::size_type;
constexpr TSize Fn(const TArray& myArray)
{
//constexpr TSize ret{myArray.size()}; return ret; // fails
return myArray.size(); // ok
}
int main()
{
constexpr TArray ar{};
constexpr TSize i{Fn(ar)};
return i;
}
我在 gcc 和 c++17 中遇到的错误是
<source>: In function 'constexpr TSize Fn(const TArray&)':
<source>:15:39: error: 'myArray' is not a constant expression
15 | constexpr TSize ret{myArray.size()}; return ret; // fails
我想补充一点,我意识到错误状态 myArray 不是常量表达式。我不能使它成为常量表达式,因为它是一个引用参数。
我的问题是 而不是 如何修复代码或使其正常工作。这就是为什么编译器接受 ok like 但不接受 fail 行?
如果删除 constexpr
,您将看到编译器接受失败行。 constexpr
的变量必须在编译时初始化(这也意味着它是隐式静态的)。但是标记为 constexpr
潜在 的函数可以 在编译时调用,但它不是必须的。它也可以在运行时调用,这样初始化就不会在编译时发生,而是在运行时发生。那是被禁止的。对于 constexpr
函数,如果删除 constexpr
.
,您应该始终考虑它们是否也可以工作
出现此行为是因为
- 出现在函数内部的表达式
myArray.size()
本身并不是常量表达式,因为它访问的引用变量的初始化在这个表达式。
- 表达式
Fn(ar)
是 常量表达式,尽管它的计算涉及函数调用内部的 myArray.size()
的计算。当 myArray.size()
作为 Fn(ar)
的一部分被评估 时,引用参数的初始化是可见的(函数调用本身执行该初始化)。
- 当你声明一个变量
constexpr
时,编译器会判断该变量的初始化是否是一个有效的常量表达式本身;
- 因此,
Fn(ar)
可用于初始化一个 constexpr
变量,但 myArray.size()
不能。
有时允许常量表达式包含本身不是常量表达式的表达式。
可能令人惊讶
除非您将标记为 ok 的行替换为标记为 fails 的行,否则以下代码将按预期编译和工作。唯一的区别是我正在创建一个本地临时 constexpr 变量。我不明白为什么它只在一种情况下失败。
#include <array>
using TArray = std::array<int, 2>;
using TSize = TArray::size_type;
constexpr TSize Fn(const TArray& myArray)
{
//constexpr TSize ret{myArray.size()}; return ret; // fails
return myArray.size(); // ok
}
int main()
{
constexpr TArray ar{};
constexpr TSize i{Fn(ar)};
return i;
}
我在 gcc 和 c++17 中遇到的错误是
<source>: In function 'constexpr TSize Fn(const TArray&)':
<source>:15:39: error: 'myArray' is not a constant expression
15 | constexpr TSize ret{myArray.size()}; return ret; // fails
我想补充一点,我意识到错误状态 myArray 不是常量表达式。我不能使它成为常量表达式,因为它是一个引用参数。
我的问题是 而不是 如何修复代码或使其正常工作。这就是为什么编译器接受 ok like 但不接受 fail 行?
如果删除 constexpr
,您将看到编译器接受失败行。 constexpr
的变量必须在编译时初始化(这也意味着它是隐式静态的)。但是标记为 constexpr
潜在 的函数可以 在编译时调用,但它不是必须的。它也可以在运行时调用,这样初始化就不会在编译时发生,而是在运行时发生。那是被禁止的。对于 constexpr
函数,如果删除 constexpr
.
出现此行为是因为
- 出现在函数内部的表达式
myArray.size()
本身并不是常量表达式,因为它访问的引用变量的初始化在这个表达式。 - 表达式
Fn(ar)
是 常量表达式,尽管它的计算涉及函数调用内部的myArray.size()
的计算。当myArray.size()
作为Fn(ar)
的一部分被评估 时,引用参数的初始化是可见的(函数调用本身执行该初始化)。 - 当你声明一个变量
constexpr
时,编译器会判断该变量的初始化是否是一个有效的常量表达式本身; - 因此,
Fn(ar)
可用于初始化一个constexpr
变量,但myArray.size()
不能。
有时允许常量表达式包含本身不是常量表达式的表达式。
可能令人惊讶