Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ if constexpr-为什么已完全选中丢弃语句?_C++_C++20_If Constexpr - Fatal编程技术网

C++ if constexpr-为什么已完全选中丢弃语句?

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

我在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&& 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
    }
}