1

Consider the following definition:

template<int n> struct Foo;
template<> struct Foo<1> { void fn1(); };
template<> struct Foo<2> { void fn2(); };

Foo<1> has a member function fn1 and similarly Foo<2> has fn2. We can use these functions, selecting the appropriate function to call using an if constexpr expression:

template<int n>
void test_template() {
    Foo<n> foo;
    if constexpr (n==1) {
        foo.fn1();
    } else {
        foo.fn2();
    }
}
template void test_template<1>(); //Interested in `Foo<1>`

This works perfectly on latest Clang, GCC, and MSVC.

We can think about doing functionally the same thing, but with a constexpr expression:

constexpr int n = 1; //Interested in `Foo<1>`
void test_constexpr() {
    Foo<n> foo;
    if constexpr (n==1) {
        foo.fn1();
    } else {
        foo.fn2();
    }
}

This fails (on all three compilers)! Specifically, all compilers' errors show that they are attempting to compile foo.fn2().

Is this behavior correct? If so, why? It seems to me like the compilation should be similar, and that the second case should work too!


EDIT: several other questions have been asked about if constexpr in the context of template instantiations (see comments). However, this is specifically about if constexpr without templates. Indeed, the template version above works as I'd expect.

According to the C++ documentation:

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

However, it also says:

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

The question is why this should be the case?


(live example on gcc.godbolt)

(Tagging this C++17, since if constexpr is a C++17 feature, though of course I am actually using C++20, and soon C++23 . . .)

geometrian
  • 14,775
  • 10
  • 56
  • 132
  • https://stackoverflow.com/q/46512248/817643 – StoryTeller - Unslander Monica Apr 21 '22 at 19:48
  • Read up on [`[temp.res.general]/6.1`](http://eel.is/c++draft/temp#res.general-6.1). – HolyBlackCat Apr 21 '22 at 19:51
  • 2
    `if constexpr` **only** works on things that depend on the template parameters – NathanOliver Apr 21 '22 at 19:51
  • 1
    These do not appear to be duplicates; they are are all about the discarded statement of an `if constexpr` within a `template`. This is specifically about the discarded statement, when *not* in a `template`. – geometrian Apr 21 '22 at 20:07
  • 1
    @imallett: I don't see why that matters. In a non-template function, *nothing* is a dependent expression, and therefore nothing gets discarded when using `if constexpr`. It's the same reasoning, just with slightly different wording. – Nicol Bolas Apr 21 '22 at 20:13
  • 1
    @imallett: "*The question is why this should be the case?*" Because that's how it was defined. `if constexpr` is not *meant* to be a replacement for `#if`. – Nicol Bolas Apr 21 '22 at 20:16
  • @NicolBolas The sections of the specification mentioned by other commenters are *specifically predicated on* being in `template` contexts. You can't arbitrarily remove that predication. In any case, the fact that in `template` contexts the statement *is* discarded suggests that it *would* work, when in fact it does not.¶ To your second comment, that would be answer (albeit I suspect one can generate a less disingenuous justification). – geometrian Apr 21 '22 at 20:21
  • 1
    @imallett: "*the fact that in template contexts the statement is discarded suggests that it would work, when in fact it does not.*" The standard (or an answer) saying that 'Y happens given context X' does not mean Y can happen in other contexts. If it doesn't say that a thing can happen, then it doesn't happen. – Nicol Bolas Apr 21 '22 at 21:15
  • "The question is why this should be the case?" Are you asking about the rationale? The proposal doesn't elaborate on it. Presumably the cost of making it work outside of templates is too big and the benefits are too small to make it worthwhile. But it is best to ask the standard committee members. – n. m. could be an AI Apr 29 '22 at 10:36

0 Answers0