本地constexpr变量引入了编译器错误

问题描述

除非您将标记为 ok 的行替换为标记为失败的行,否则以下代码将按预期的方式编译和运行。唯一的不同是,我正在制作一个本地临时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 而不接受 fail 行的原因?

解决方法

出现此现象的原因是

  • 出现在函数内部的表达式myArray.size()本身不是常量表达式 ,因为它访问的引用变量的初始化在该表达式的上下文中不可见。 li>
  • 表达式Fn(ar) 是一个常数表达式,尽管其评估涉及函数调用中myArray.size()的评估。当myArray.size()作为{em> Fn(ar)的一部分被评估时,参考参数的初始化是可见的(函数调用本身执行该初始化)。
  • 声明变量constexpr时,编译器将确定该变量的初始化是否为有效的常量表达式本身;
  • 因此,Fn(ar)可用于初始化constexpr变量,但myArray.size()可能不会。

令人惊讶的是,有时允许常量表达式包含本身不是 常量表达式的表达式。

,

如果您删除constexpr,将会看到编译器接受失败行。 constexpr变量必须在编译时初始化(这也意味着它是隐式静态的)。但是标记为constexpr的函数可能在编译时被调用 ,但不是必须的。也可以在运行时调用它,然后,此初始化将不在编译时,而是在运行时。那是被禁止的。对于constexpr函数,您应该始终考虑一下,如果删除constexpr,它们是否也会起作用。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...