user19584800
user19584800

Reputation: 29

Static Assert unexpected behaviour

Here is the code which has unexpected behaviour:

#include<iostream>
using namespace std;

namespace n1{
    namespace n2{
        enum comparator_t {
          LT = 0, /*!< less-than < */
          LE = 1, /*!< less-than-or-equal-to, i.e. <= */
        };
    }
}
int main(){
    int32_t const INF_VALUE = INT32_MAX >> 1;
    int32_t const MINUS_INF_VALUE = INT32_MIN >> 1; 
    
    int32_t const LT_INFINITY = (INF_VALUE << 1) | n1::n2::LT;
    int32_t const LE_MINUS_INFINITY = (MINUS_INF_VALUE << 1) | n1::n2::LE;

    int32_t const LE_ZERO = (0 << 1) | n1::n2::LE;
    
    static_assert(LE_ZERO != LT_INFINITY, "");
    static_assert(LE_ZERO != LE_MINUS_INFINITY, "");    
}

The above C++ code gives a compilation error:

error: non-constant condition for static assertion

However, when the last line of the code is commented (//static_assert(LE_ZERO != LE_MINUS_INFINITY, "");), the code compiles properly. The definition of LE_MINUS_INFINITY and INF_VALUE look very similar, so why is the code not compiling?

Upvotes: 2

Views: 79

Answers (1)

Adrian Mole
Adrian Mole

Reputation: 51825

The problem is with this line:

int32_t const LE_MINUS_INFINITY = (MINUS_INF_VALUE << 1) | n1::n2::LE;

Up until the C++20 Standard, left-bit-shifting a negative signed integer value is undefined behaviour. Your compiler (rightly) refuses to accept the result of that UB as a compile-time constant.

Changing to use the -std=c++20 (or equivalent, for your compiler) fixes the issue. See on Compiler Explorer.

Upvotes: 4

Related Questions