Kiedy chcemy używać static_assert
w sposób if constexpr
musimy warunek zależny od jakiegoś parametru szablonu. Co ciekawe, gcc i clang nie zgadzają się, gdy kod jest zawarty w lambda.
Poniższy kod kompiluje się z gcc, ale clang wyzwala aser, nawet jeśli if constexpr
nie może to być prawda.
#include <utility>
template<typename T> constexpr std::false_type False;
template<typename T>
void foo() {
auto f = [](auto x) {
constexpr int val = decltype(x)::value;
if constexpr(val < 0) {
static_assert(False<T>, "AAA");
}
};
f(std::integral_constant<int, 1>{});
}
int main() {
foo<int>();
}
Można to łatwo naprawić, zastępując False<T>
przez False<decltype(x)>
.
Pytanie brzmi: który kompilator ma rację? Zakładam, że gcc jest poprawny, ponieważ warunek w static_assert
zależy od T
, ale nie jestem pewien.
static_assert(False<int>, "AAA");
jest równoważne z static_assert(false, "AAA");
wewnątrz lambda.
f(std::integral_constant<int, 1>{});
Wandbox, nie wyzwala potwierdzenia: wandbox.org/permlink/UFYAmYwtt1ptsndr