Why doesn't an if constexpr make this core constant expression error disappear?

前端 未结 3 1118
盖世英雄少女心
盖世英雄少女心 2020-12-05 06:52

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.<

相关标签:
3条回答
  • 2020-12-05 07:30

    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. In an enclosing template discarded statements are not instantiated.
    2. Names referenced from a discarded statement are not required ODR to be defined.

    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;
        }
    }
    

    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>();
    }
    
    0 讨论(0)
  • 2020-12-05 07:32

    I'm not sure why you expect the branch to not be checked. The only time an if branch is "not checked" is when it is part of a template and not instantiated, as per [stmt.if]p2:

    During the instantiation of an enclosing templated entity (Clause 17), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

    Your code doesn't seem to be in a situation where this applies.

    0 讨论(0)
  • 2020-12-05 07:41

    Note that for the statement discarded by Constexpr If:

    the discarded statement can't be ill-formed for every possible specialization:

    To fix the issue you can make the statement depending on the template parameter, e.g.

    template<typename T, int X> struct dependent_value { constexpr static int V = X; };
    
    template <typename T>
    void foo() {
        constexpr int x = -1;
        if constexpr (x >= 0){
            constexpr int y = 1 << dependent_value<T, x>::V;
        }
    }
    

    LIVE

    0 讨论(0)
提交回复
热议问题