C++ if constexpr-为什么已完全选中丢弃语句?
我在GCC10中使用c++20 consteval,并编写了以下代码C++ if constexpr-为什么已完全选中丢弃语句?,c++,c++20,if-constexpr,C++,C++20,If Constexpr,我在GCC10中使用c++20 consteval,并编写了以下代码 #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&&a
#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;
}
}
#包括
#包括
#包括
模板
consteval std::可选的find_if_impl(谓词和pred,
元组(&t)无例外{
constexpr std::size\u t I=std::tuple\u size\u v-N;
如果constexpr(N==0u){
返回std::nullopt;
}否则{
返回pred(std::get(t))
?标准::使_可选(I)
:如果执行(std::forward(pred)),则查找,
标准:正向(t));
}
}
模板
consteval std::可选的find_if(谓词和pred,
元组(&t)无例外{
返回find\u if\u impl(
std::forward(pred),std::forward(t));
}
constexpr auto is_integral=[](auto&&x)无例外{
返回标准::为整数值;
};
int main(){
auto t0=std::make_tuple(9,1.f,2.f);
constexpr auto i=find_if(是_积分,t0);
如果constexpr(i.具有_值()){
std::cout这就是工作原理。如果我们检查
如果If语句的形式为If constexpr,则条件的值应为bool类型的上下文转换常量表达式;这种形式称为constexpr If语句。如果转换条件的值为false,则第一个子语句为丢弃语句,否则第二个子语句(如果存在)为discarded语句。在实例化封闭模板实体([temp.pre])期间,如果条件在实例化后不依赖于值,则不会实例化丢弃的子语句(如果有)。[…]
重点矿山
因此,我们可以看到,只有在模板中且条件依赖于值的情况下,才不会对丢弃的表达式求值。main
不是函数模板,因此编译器仍会检查if语句的主体是否正确
Cppreference在关于constexpr的章节中也提到了这一点,如果:
如果constexpr If语句出现在模板化实体内,并且实例化后条件不依赖于值,则在实例化封闭模板时不会实例化丢弃的语句
template<typename T, typename ... Rest>
void g(T&& p, Rest&& ...rs) {
// ... handle p
if constexpr (sizeof...(rs) > 0)
g(rs...); // never instantiated with an empty argument list.
}
虽然AndyG不解决它,是吗?X你知道C++的推理吗?看起来这将是一个很好的适合CONEXPRPR的解决方案。同样的解决方案是,例如,将它封装在模板中。“YaaHaRi,因为C++模板的结构比你希望的要少,而且是的,用模板把它包起来。(或者像i.value\u或(0)
)那样编写)@Yamahari是的,解决方案是将代码放入函数模板中。就推理而言,我不知道为什么。这可能是一个好问题。@Barry value\u或(0)很好,但适用于元组大小为0的情况
void f() {
if constexpr(false) {
int i = 0;
int *p = i; // Error even though in discarded statement
}
}