Search code examples
c++c++17if-constexpr

if constexpr(condition) as compile-time conditional


I want to use a constexpr bool (useF in the example below) to enable a feature in the following code. Here, calling A::f(). Additionally, I want to be the alias-template (a) to be void in the case I switch off the feature.

I tried to use a constexpr if statement, but the body is still being instantiated, which causes a compile error. If I use a wrapper template (X), the body is being discarded as I'd expected, but that seems ugly to me. Are there any other ways to do this?

constexpr bool useF = false;

struct A {
    static void f() {}
};

using a = std::conditional<useF, A, void>::type;

template<typename L>
struct X {
    static void h() {
        if constexpr(std::is_same<L, A>::value) {
            L::f(); // not instantiated, no error
        }
    }
};

int main() {
    if constexpr(useF) {
        a::f(); // error!?
    }

    X<a>::h();
}

I am using g++-7.0.1 with -std=c++17


Solution

  • if constexpr is only for templates. From [stmt.if]:

    If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool (5.20); this form is called a constexpr if statement. If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantation of an enclosing templated entity (Clause 14), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

    Within X, the constexpr if statement will prevent the otherwise ill-formed statement from being instantiated. That is the goal of this language feature. But outside of templates, there's no such equivalent gain.