0

I wanted to wrap both constexpr and non-constexpr behaviour inside a function and that seems possible (ref : calling non constexpr function from constexpr allowed in some conditions)

Following shows same snippet:

void bla( )
{
    std::cout << "bla called!" << std::endl;
}

constexpr bool check(bool condition)
{
    //bla(); // can not directly be called -> not constexpr! 
    condition ? void (0) : bla(); // compiles and runs even if condition is true or false!

    
    true ? void(0): bla(); // also that compiles!, ok, directly evaluated
    
    false ? bla(): void(0); // compiles, ok, directly evaluated

    return 0;
}

int main()
{
    check( false );
    check( true );
}

So check(false) works and I am able to call bla() (a non-constexpr function) from constexpr function as expected (reasong being given in the ans in the link).

My usecase is I want to use this constexpr function inside if constexpr.. and that fails:

void bla( )
{
    std::cout << "bla called!" << std::endl;
}

constexpr bool check(bool condition)
{
    //bla(); // can not directly be called -> not constexpr! 
    condition ? void (0) : bla(); // compiles and runs even if condition is true or false!

    
    true ? void(0): bla(); // also that compiles!, ok, directly evaluated
    
    false ? bla(): void(0); // compiles, ok, directly evaluated

    return 0;
}

int main()
{
    if constexpr(check( false )){}; // throws compiler error
    if constexpr(check( true )){};
}

above snippet: https://godbolt.org/z/4c5PvEhcb

Is it possible to call if constexpr on above function? My use-case in general is: I want to have two version of a function depending upon build flags but both are called from if constexpr to keep rest of the code clean. Minimal example:

#include <iostream>
#define SIMULATION
size_t get_count() { return 10; }

#if defined(SIMULATION)
    inline constexpr bool func(bool compile_time_flag = false) // compile_time_flag param added so that one of the evaluation of the function is constexpr (when flag = true)
    {
        bool ret_val = false;
        ret_val = compile_time_flag ? false : (get_count() > 1);
        return ret_val;
    }
#else
    inline constexpr bool func(bool compile_time_flag = true)
    {
        return false;
    };
#endif

//somewhere in code
int main()
{
    if constexpr(func())
    {
        std::cout << " It works! ";
    }
    return 0;
}

above snippet: https://godbolt.org/z/4KhcabPqn. Doesn't work when SIMULATION is defined.

Is it possible what I am trying to do? I don't want to wrap the whole usage of constexpr(func()) vs (func()) depending upon build flag (looks ugly):

#if define SIMULATION
# define CHECK_COND (func())
#else
# define CHECK_COND constexpr(func())
int main()
{
    if CHECK_COND
    {
        std::cout << " It works! ";
    }
    return 0;
}

Dont want to do above, which should work.

Is there a better way to acheive the same? Thanks!

Akash
  • 939
  • 1
  • 8
  • 27
  • 2
    The naming is unfortunate - `constexpr function` must be runnable at compile time if and only if required by the context. `constexpr if` is always evaluated at compile = always runs the function at compile time. So basically you can only run functions could be marked `consteval`. – Quimby Aug 01 '23 at 10:39
  • That a function is declared `constexpr` means this: If the function is called in a `constexpr` context, such as the condition of an `if constexpr` statement, then the compiler will _try_ to evaluate the function at compile time. If that evaluation cannot happen at compile time (as in your example), compilation will fail. If the function was not declared `constexpr` the compiler would not even try to evaluate it at compile time. – chrysante Aug 01 '23 at 11:00
  • I get that - Ok. constexpr if is basically consteval if. But is there a better way to do what I want to acheive? @Quimby – Akash Aug 01 '23 at 11:06
  • @Akash `check( false )` is not a constant expression no matter what because it would intentionally evaluate a function that is not marked `constexpr`. So the compiler simply cannot make sense of that in compile time contexts such as an `if constexpr` condition. – user17732522 Aug 01 '23 at 11:10
  • @Akash If your code supports both the `if` condition with `constexpr` as well as without depending on a macro, then what is the point of having it be `if constexpr` at all? Why is just `if` not sufficient? – user17732522 Aug 01 '23 at 11:11
  • @user17732522 I don't want to have if () when working without a certain build flag(for latency reasons - SIMULATION in this example), while its okay to have that when using the build flag. – Akash Aug 01 '23 at 11:13
  • @Akash I think you want [something from this](https://stackoverflow.com/questions/46919582/is-it-possible-to-test-if-a-constexpr-function-is-evaluated-at-compile-time) as a wrapper, similarly to your macro. – Quimby Aug 01 '23 at 11:13
  • 1
    @Akash Why do you expect `if constexpr` vs `if` to make a latency/performance difference? The compiler will still do constant-folding and other optimization on the `if` condition even if it is not in a constant expression context. The purpose of `if constexpr` is to enable writing generic code in which one branch isn't well-formed for certain specializations. It is not primarily meant for performance improvements. – user17732522 Aug 01 '23 at 11:15
  • @user17732522 I get your point, and agree to that. But the fact that if constexpr is able to remove branching during compiling explicitly makes the code cleaner. I hope I make some sense. It might be a bad design to go with this, I don't know. Morever I was curious if that was at all possible. – Akash Aug 01 '23 at 11:26

0 Answers0