2

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?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 3
    Even for small examples, please [don't include that `` header file](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h), it's *always* wrong. – Some programmer dude Jul 24 '22 at 07:46
  • What compiler is producing this objection? – tadman Jul 24 '22 at 07:51
  • 1
    As for your problem, please [build with extra warnings enabled](https://godbolt.org/z/qnM8abc83). That will indicate a major problem. Hint: For bitwise operations, always use *unsigned* integer types. – Some programmer dude Jul 24 '22 at 07:51
  • Is that the entire error message? Both GCC and Clang explain in plain English why they don't like the second assert. And interestingly, the code compiles with `-std=c++20`. – HolyBlackCat Jul 24 '22 at 07:51
  • @user19584800 the output of command ```g++ --version``` is ```g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0``` – user19584800 Jul 24 '22 at 07:53

1 Answers1

4

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.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83