c++gccassertionc++20constant-expression

How to get a compile time error in constant evaluated expression?


I have an Assert function that I use to evaluate assertion:

I would like that this function also generates a compile time error when the assertion fails in constant evaluated expression:

const int a = (Assert(false),0); //generate a runtime error 
                                 //=> I would like it generates a compile time error

I thought about using std::is_constant_evaluated: compiler-explorer

#include <type_traits>

using namespace std;

void runtime_error();

constexpr void compile_time_error(){} //should generates a compile time error

constexpr void Assert(bool value){
   if (value) return;
   if (is_constant_evaluated())
     compile_time_error();
   else
     runtime_error();
   }

void func(){
    const int a = (Assert(false),0);
    }

I only use GCC, I have look for a builtin function that would cause a compile time error and that would be a constexpr but did not find one.

Is there any trick to get a compile time error in expression that could be constant evaluated?


Solution

  • You can call a function that is nowhere defined to cause a compile time error. Or, since you are using gcc anyway, you can call a attribute error function from inside the constant part to cause a compile time error during compilation of this unit. To make it work, you have to compile with optimizations enabled.

    I see that with std::is_constant_expression it does not work in gcc 9.2, but I managed it to work with __builtin_constant_p.

    #include <type_traits>
    
    constexpr void Assert(bool value) {
       if (__builtin_constant_p(value)) {
            if (!value) {
                extern __attribute__(( __error__ ( "error" ) ))
                void compile_time_error(void);
                compile_time_error();
            }
        } else {
            if (!value) {
                void runtime_error();
                runtime_error();
            }
       }
    }
    
    void func(int b) {
        const int a = (Assert(false), 0);
        Assert(b == 0);
    }
    

    I have once written a library in C I called curb that would do something like this.