Ich habe mit C ++ 20 Consteval in GCC 10 herumgespielt und diesen Code geschrieben
#include <optional>
#include <tuple>
#include <iostream>
template <std::size_t N, typename Predicate, typename Tuple>
consteval std::optional<std::size_t> find_if_impl(Predicate&& pred,
Tuple&& t) noexcept {
constexpr std::size_t I = std::tuple_size_v<std::decay_t<decltype(t)>> - N;
if constexpr (N == 0u) {
return std::nullopt;
} else {
return pred(std::get<I>(t))
? std::make_optional(I)
: find_if_impl<N - 1u>(std::forward<decltype(pred)>(pred),
std::forward<decltype(t)>(t));
}
}
template <typename Predicate, typename Tuple>
consteval std::optional<std::size_t> find_if(Predicate&& pred,
Tuple&& t) noexcept {
return find_if_impl<std::tuple_size_v<std::decay_t<decltype(t)>>>(
std::forward<decltype(pred)>(pred), std::forward<decltype(t)>(t));
}
constexpr auto is_integral = [](auto&& x) noexcept {
return std::is_integral_v<std::decay_t<decltype(x)>>;
};
int main() {
auto t0 = std::make_tuple(9, 1.f, 2.f);
constexpr auto i = find_if(is_integral, t0);
if constexpr(i.has_value()) {
std::cout << std::get<i.value()>(t0) << std::endl;
}
}
Dies soll wie der STL-Suchalgorithmus funktionieren, jedoch für Tupel. Statt einen Iterator zurückzugeben, wird ein optionaler Index zurückgegeben, der auf einem Prädikat für die Kompilierungszeit basiert. Jetzt wird dieser Code einwandfrei kompiliert und ausgedruckt
9
Wenn das Tupel jedoch kein Element enthält, das ein integraler Typ ist, wird das Programm nicht kompiliert, da i.value () weiterhin für ein leeres optionales Element aufgerufen wird. Warum ist das so?
c++
c++20
if-constexpr
Yamahari
quelle
quelle
Antworten:
So funktioniert constexpr if . Wenn wir [stmt.if] / 2 überprüfen
Betonung meiner
Wir können also sehen, dass wir den verworfenen Ausdruck nur dann nicht auswerten, wenn wir uns in einer Vorlage befinden und wenn die Bedingung wertabhängig ist.
main
ist keine Funktionsvorlage, daher wird der Hauptteil der if-Anweisung vom Compiler weiterhin auf Richtigkeit überprüft.Cppreference sagt dies auch in ihrem Abschnitt über constexpr, wenn mit:
quelle
i.value_or(0)
)