constexpr为什么不使这个核心常量表达式错误消失

constexpr为什么不使这个核心常量表达式错误消失

本文介绍了if constexpr为什么不使这个核心常量表达式错误消失?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考此问题.用于初始化constexpr变量y的核心常量表达式格式错误.给定了这么多.

In reference to this question. The core constant expression that is used to initialize the constexpr variable y is ill-formed. So much is a given.

但是,如果我尝试将if转换为if constexpr:

But if I try to turn the if into an if constexpr:

template <typename T>
void foo() {
    constexpr int x = -1;
    if constexpr (x >= 0){
        constexpr int y = 1 << x;
    }
}

int main(){
    foo<int>();
}

错误仍然存​​在.在GCC 7.2仍能提供的情况下:

The error persists. With GCC 7.2 still giving:

error: right operand of shift expression '(1 << -1)' is negative [-fpermissive]

但是我认为应该在丢弃的分支上不进行语义检查.

But I thought that the semantic check should be left unpreformed on a discarded branch.

通过constexpr lambda进行间接寻址确实有帮助,但是:

Making an indirection via a constexpr lambda does help, however:

template <typename T>
void foo(){
    constexpr int x = -1;
    constexpr auto p = []() constexpr { return x; };
    if constexpr (x >= 0){
        constexpr int y = 1<<p();
    }
}

y上的constexpr说明符似乎改变了检查废弃分支的方式.这是预期的行为吗?

The constexpr specifier on y seems to alter how the discarded branch is checked. Is this the intended behavior?

@ max66 足以检查其他实现.他报告说,GCC(7.2.0/Head 8.0.0)和Clang(5.0.0/Head 6.0.0)均可重现该错误.

@max66 was kind enough to check other implementations. He reports that the error is reproducible with both GCC (7.2.0 / Head 8.0.0) and Clang (5.0.0 / Head 6.0.0).

推荐答案

该标准对if constexpr废弃声明并没有多说. [stmt.if]中基本上有两个关于这些的语句:

The standard doesn't say much about the discarded statement of an if constexpr. There are essentially two statements in [stmt.if] about these:

  1. 在封闭模板中,未实例化丢弃的语句.
  2. 从废弃语句引用的名称不需要定义ODR.

这两种都不适合您使用:如果初始化,编译器会抱怨constexpr是正确的.请注意,当您想利用实例失败时,需要使条件依赖于模板参数:如果该值不依赖于模板参数,则当模板是定义的.例如,此代码仍然失败:

Neither of these applies to your use: the compilers are correct to complain about the constexpr if initialisation. Note that you'll need to make the condition dependent on a template parameter when you want to take advantage of the instantiation to fail: if the value isn't dependent on a template parameter the failure happens when the template is defined. For example, this code still fails:

template <typename T>
void f() {
    constexpr int x = -1;
    if constexpr (x >= 0){
        constexpr int y = 1<<x;
    }
}

但是,如果使x依赖于类型T,即使使用int实例化f也是可以的:

However, if you make x dependent on the type T it is OK, even when f is instantiated with int:

template <typename T>
void f() {
    constexpr T x = -1;
    if constexpr (x >= 0){
        constexpr int y = 1<<x;
    }
}
int main() {
    f<int>();
}

这篇关于if constexpr为什么不使这个核心常量表达式错误消失?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 12:35