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

An 'if constexpr branch' does not get discarded inside lambda that is inside a template function


The following code:

#include <type_traits>

struct X {
    static constexpr void x() {}
};

template <class T1, class T2>
constexpr bool makeFalse() { return false; }

template <class T>
void foo() {
    T tmp;
    auto f = [](auto type) {
        if constexpr (makeFalse<T, decltype(type)>()) {
            T::x(); // <- clang does not discard
        } else {
            // noop
        }
    };
}

int main() {
    foo<int>();
}

does not compile with Clang, but compiles with GCC. I can't see anything wrong with this code, but I'm not sure. Is Clang right not compiling it?


Solution

  • [stmt.if]/2:

    During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

    Since makeFalse<T, decltype(type)>() is value-dependent after the instantiation of foo<int>, it appears that T::x() should be instantiated per the standard, and since T::x is ill-formed when T is int, Clang is right not compiling it.