Je déconnais avec c ++ 20 consteval dans GCC 10 et écrivais ce code
#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;
}
}
Qui est censé fonctionner comme l'algorithme de recherche STL mais sur des tuples et au lieu de renvoyer un itérateur, il retourne un index facultatif basé sur un prédicat de temps de compilation. Maintenant, ce code se compile très bien et il s'imprime
9
Mais si le tuple ne contient pas d'élément de type intégral, le programme ne compile pas, car i.value () est toujours appelé sur une option vide. Maintenant, pourquoi ça?
c++
c++20
if-constexpr
Yamahari
la source
la source
Réponses:
C'est ainsi que constexpr fonctionne. Si nous vérifions [stmt.if] / 2
mettre l'accent
Nous pouvons donc voir que nous n'évaluons l'expression que si nous sommes dans un modèle et si la condition dépend de la valeur.
main
n'est pas un modèle de fonction, donc le corps de l'instruction if est toujours vérifié par le compilateur pour l'exactitude.Cppreference le dit également dans leur section sur constexpr si avec:
la source
i.value_or(0)
)