1

Consider the following code:

enum { a = 1, b = 2 - a};

void foo() {
    if constexpr(a == 1) { }
    else { static_assert(b != 1, "fail :-("); }
}

naively, one might expect the static_assert() to never be triggered, since the if constexpr condition holds. But - it is triggered (GodBolt).

What C++ mechanism should I use instead, to ensure failure only when the condition of an if statement evaluates to false?

4
  • 2
    static_assert(a == 1 || b != 1, "fail :-("); Since a static_assert isn't scoped in this case (... because it is static and not in a template), so doesn't matter that it is in the else block. Commented Mar 18 at 21:57
  • 1
    @Eljay: I "don't know" about a as I write the static asseration, or whatever alternative I use. Also, DRY. Commented Mar 18 at 22:07
  • How can I create a type-dependent expression that is always false? Commented Mar 18 at 23:44
  • 1
    AFAIK if constexpr has no meaning outside a template. It's purpose is to eliminate the branching when the template is instantiated (hence the need to have a constexpr condition). In your case, it's equivalent to a regular if but restricted to constexpr conditions only (which is then useless). Commented Mar 19 at 9:41

1 Answer 1

1

What C++ mechanism should I use instead, to ensure failure only when the condition of an if statement evaluates to false?

According to cppreference

Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive:

so I suppose you can make your foo() function a template one

template <int = 0>
void foo() {
    if constexpr(a == 1) { }
    else { static_assert(b != 1, "Fail"); }
}

--- EDIT ---

The OP asks

it's quite problematic to change the function definition just for an assertion somewhere... can't I use some kind of templated gadget instead?

I don't see a way through a type trait.

But if you can use at least C++20, so template lambdas, you can wrap your code inside a template lambda defined inside the foo() function. And call the lambda.

I mean something as follows

enum { a = 1, b = 2 - a};

void foo() {
  auto l = []<int = 0>{
    if constexpr (a == 1) {
    }
    else {
      static_assert(b != 1, "fail :-(");
    }
  };

  l();
}

int main ()
{
  foo();
}
Sign up to request clarification or add additional context in comments.

6 Comments

I guess that's an option, but it's quite problematic to change the function definition just for an assertion somewhere... can't I use some kind of templated gadget instead?
@einpoklum - I've edited my answer. Yes... if C++20 is OK, you can use a sort of templated gadget. you can wrap your code in a templated lambda.
It's still messing with the other branch of the if()... I want something which will replace static_assert(...), and nothing else. But - maybe I have no recourse other than macros. PS - If it's doable without choosing the error string, that might still be useful.
@einpoklum - something inside the else branch that gives a compilation error when the else branch is compiled? The problem is that, without templates, the else branch is ever compiled (if I understand correctly what cppreference says). Maybe a static_assert, outside the if/then/else, that fail when the if condition fails?
It can be shrunk a bit, if it helps: godbolt.org/z/cGevY6jE5
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.