Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 360
nicolai Avatar asked Apr 29 '19 18:04

nicolai


1 Answers

[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.

like image 73
cpplearner Avatar answered Nov 19 '22 02:11

cpplearner