简体   繁体   English

为什么用成员数组调用constexpr函数而不是常量表达式?

[英]Why is calling a constexpr function with a member array not a constant expression?

I have the following helper function: 我有以下帮助函数:

template<typename T, std::size_t N>
constexpr std::size_t Length(const T(&)[N]) {
    return N;
}

Which returns the length of a static array. 返回静态数组的长度。 In the past this always has worked but when I do this: 在过去,这总是有效,但当我这样做时:

struct Foo
{
    unsigned int temp1[3];
    void Bar()
    {
        constexpr std::size_t t = Length(temp1); // Error here
    }
};

I get an error when using MSVS 2017: 使用MSVS 2017时出错:

 error C2131: expression did not evaluate to a constant note: failure was caused by a read of a variable outside its lifetime note: see usage of 'this' 

I was hoping someone can shed light on what I'm doing wrong. 我希望有人能说清楚我做错了什么。

MSVC is correct. MSVC是正确的。 Length(temp1) is not a constant expression. Length(temp1)不是常量表达式。 From [expr.const]p2 来自[expr.const] p2

An expression e is a core constant expression unless the evaluation of e , following the rules of the abstract machine, would evaluate one of the following expressions: 表达式e是核心常量表达式,除非根据抽象机器的规则评估e将评估以下表达式之一:

  • this , except in a constexpr function or a constexpr constructor that is being evaluated as part of e ; this ,除了在constexpr函数或constexpr构造函数中被评估为e的一部分;

temp1 evaluates this implicitly (because you are referring to this->temp1 ), and so you don't have a constant expression. temp1隐式计算this (因为你指的是this->temp1 ),所以你没有常量表达式。 gcc and clang accept it because they support VLAs as an extension (try compiling with -Werror=vla or -pedantic-errors ). gcc和clang接受它,因为它们支持VLA作为扩展(尝试使用-Werror=vla-pedantic-errors编译)。

Why isn't this allowed? 为什么不允许这样做? Well, you could access the underlying elements and potentially modify them. 好吧,您可以访问底层元素并可能修改它们。 This is completely fine if you are dealing with a constexpr array or an array that is being evaluated as a constant expression, but if you are not, then you cannot possibly have a constant expression as you will be manipulating values that are set at run time. 如果你正在处理一个constexpr数组或一个被评估为常量表达式的数组,这是完全正常的,但如果不是,那么你不可能有一个常量表达式,因为你将操纵在运行时设置的值。

Length(decltype(temp1){})

seems to work . 似乎工作

Unfortunately, I cannot comment, but Mehrdad 's solution is wrong. 不幸的是,我无法评论,但Mehrdad的解决方案是错误的。 The reason: it is not technically undefined behavior but it is undefined behavior. 原因是:它不是技术上未定义的行为, 未定义的行为。 During constexpr evaluation, the compiler must catch undefined behavior. 在constexpr评估期间,编译器必须捕获未定义的行为。 Therefore, the code is ill-formed . 因此, 代码是不正确的

Your question's already been answered, but in terms of how to "fix" it, a quick-and-dirty way is to replace 你的问题已经得到了回答,但就如何“修复”而言,一种快速而又肮脏的方式就是取而代之

Length(temp1)

with

Length(*(true ? NULL : &temp1))

which I think is technically undefined behavior but practically going to work fine for MSVC. 我认为这是技术上未定义的行为,但实际上对MSVC来说工作正常。

If you need a solution that works despite the UB, you can change Length to use a pointer: 如果您需要一个尽管有UB的解决方案,您可以更改Length以使用指针:

template<typename T, std::size_t N>
constexpr std::size_t Length(const T(*)[N]) {
    return N;
}

and then you can use Length(true ? NULL : &temp1) . 然后你可以使用Length(true ? NULL : &temp1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 constexpr 构造函数需要常量成员 function 的问题 - problem with constexpr constructor requiring constant member function constexpr - 函数不能用于常量表达式 - constexpr - function cannot be used in a constant expression 什么决定了 constexpr function 是否是常量表达式? - What determines whether a constexpr function is a constant expression? 返回常量表达式不需要constexpr函数吗? - A constexpr function is not required to return a constant expression? g ++抱怨constexpr函数不是常量表达式 - g++ complains constexpr function is not a constant expression 为什么在constexpr非成员函数中访问全局非常量变量是不合法的 - Why is it not legal to access global non constant variable in constexpr non member function 通过引用调用constexpr方法 - 结果是一个常量表达式吗? - Calling a constexpr method through a reference - is the result a constant expression? 即使成员函数是constexpr,为什么还需要constexpr? - Why is constexpr required even though member function is constexpr? 为什么在调用此constexpr静态成员函数时不将其视为constexpr? - Why is this constexpr static member function not seen as constexpr when called? 为什么没有if constexpr使这个核心常量表达式错误消失? - Why doesn't an if constexpr make this core constant expression error disappear?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM