3

If I have a constexpr function that can raise an exception at runtime, I want to make it able to give a compile error if it's evaluated at compile time.

#include <stdexcept>
#include <type_traits>

constexpr void func (const int x)
{
    if (x == 0) {
        if (std::is_constant_evaluated()) {
            /// compile error
        } else {
            throw std::invalid_argument("x cannot be 0.");
        }
    }
}

I have tried putting static_assert inside the if statement, but it evaluates it regardless of the if statement (since the if is not constexpr I'm assuming). I have also tried static_assert(x != 0);, but it tells me non-constant condition for static assertion (which makes some sense...?).

Is there any (preferably easy) way to do this? Thanks.

EDIT: I generalized the function, in my case I have a constructor that I need to use to generate both compile time and run time objects. So I would like the program to give a compile error with a message like x cannot be 0 if I try to create a constexpr object with x being 0.

H-005
  • 467
  • 3
  • 15
  • you are missing a `}` and adding the includes makes it simpler for others to compile your code – 463035818_is_not_an_ai Apr 13 '22 at 09:10
  • This seems related to [this question](https://stackoverflow.com/q/39742883/8658157), which would imply that there's no solution. – Elliott Apr 13 '22 at 09:11
  • you cannot raise a compiler error depending on a runtime variable `x` – 463035818_is_not_an_ai Apr 13 '22 at 09:11
  • is making `x` a template argument an option? – 463035818_is_not_an_ai Apr 13 '22 at 09:12
  • 3
    Did you try just removing the check and throwing at compile time? – Artyer Apr 13 '22 at 09:13
  • What exactly do you want to achieve? If you want to a compilation error if this is evaluated in a context requiring a constant expression, then just throwing is sufficient. Otherwise, whether or not a function is evaluated at compile time is up to the compiler and there isn't really anything you can do to force it not to evaluate at compile-time (how would you observe the difference anyway?). – user17732522 Apr 13 '22 at 09:15
  • 1
    @user17732522 Just throwing really generates an error, but the error message is misleading since it is not related to the invalid argument: https://godbolt.org/z/vsP189KaT – Daniel Langr Apr 13 '22 at 09:20
  • @DanielLangr Of course it is up to the compiler whether it will give details on why the expression is not a constant expression, but using an array length is an atypical example since GCC supports VLAs and therefore doesn't produce the same diagnostic it would in other situations that require a constant expression, see e.g.: https://godbolt.org/z/YTj9ooaqf. Except making the expression not a constant expression, there is no way to cause a compilation failure based on the evaluation of the function. Mechanism are throwing, calling a non-`constexpr` function, etc. – user17732522 Apr 13 '22 at 09:40
  • @463035818_is_not_a_number I generalized the example, but basically I have this: the function is a constructor for a class. If I create a constexpr object and give it x = 0, I want to generate a compile error, but if the object is not constexpr, I want it to throw. I will add this in the question. – H-005 Apr 13 '22 at 10:01
  • @Artyer I can do that, but it doesn't generate the error that I want, instead it says that `throw` is not a constant expression. Which kinda works I guess, since it compiles if `x` is not 0, but I would rather have a more concise message. `expression ‘’ is not a constant expression` does not say much. – H-005 Apr 13 '22 at 10:04

0 Answers0