在诉讼中的constexpr

constexpr in for-Statement

本文关键字:constexpr 诉讼中      更新时间:2023-10-16

c 17提供if constexpr,其中:

条件的值必须是类型bool的上下文转换的常数表达。如果该值为true,则丢弃语句 - false(如果存在(,则丢弃语句 - 真实

也有办法在for统计中使用它吗?在编译时展开循环?我喜欢做这样的事情:

template <int T>
void foo() {
   for constexpr (auto i = 0; i < T; ++i) cout << i << endl;
}

还有一种方法可以在陈述中使用它吗?在编译时展开循环?我喜欢做这样的事情

我不以一种简单的方式思考。

但是,如果您可以负担得起辅助功能,则使用std::integer_sequence和未使用的C风格整数阵列的初始化,从C 14开始,您可以按照以下操作

#include <utility>
#include <iostream>
template <int ... Is>
void foo_helper (std::integer_sequence<int, Is...> const &)
 {
   using unused = int[];
   (void)unused { 0, (std::cout << Is << std::endl, 0)... };
 }
template <int T>
void foo ()
 { foo_helper(std::make_integer_sequence<int, T>{}); }
int main ()
 {
   foo<42>();
 }

如果您可以使用C 17,则可以避免使用unused数组,并且使用折叠,foo_helper()可以简单地写入如下

template <int ... Is>
void foo_helper (std::integer_sequence<int, Is...> const &)
 { ((std::cout << Is << std::endl), ...); }

如果编译器已知循环限制,则编译器将揭开循环,如果发现它有益。并非所有循环展开都是有益的!而且,您不太可能做出比编译器更好的决定。

不需要constexpr for(如您所说的(,因为constexpr if正在启用功能 - 您可以放置代码,该代码将使程序在constexpr if False Branch内部不构建,这不是纯粹的优化。

。 另一方面,

Constexpr for将是纯粹的优化(至少如您所描述的那样,不计算0次执行的环路案例(,因此最好将" AS-IF"优化规则保留。

不是没有辅助代码。

#define RETURNS(...) 
  noexcept(noexcept(__VA_ARGS__)) 
  -> decltype(__VA_ARGS__) 
  { return __VA_ARGS__; }
template<std::size_t I>
using index_t = std::integral_constant<std::size_t, I>;
template<std::size_t...Is>
constexpr auto index_over( std::index_sequence<Is...> ) noexcept(true) {
  return [](auto&& f)
    RETURNS( decltype(f)(f)( index_t<Is>{}... ) );
}
template<std::size_t N>
constexpr auto index_upto( index_t<N> ={} ) noexcept(true) {
  return index_over( std::make_index_sequence<N>{} );
}
template<class F>
constexpr auto foreacher( F&& f ) {
  return [&f](auto&&...args) noexcept( noexcept(f(args))&&... ) {
    ((void)(f(args)),...);
  };
}

那是我们的管道。

template<int T>
void foo() {
  index_upto<T>()(
    foreacher([](auto I){
      std::cout << I << "n";
    })
  );
}

每个步骤上具有值的编译时循环。

,或者我们可以隐藏详细信息:

template<std::size_t start, std::size_t length, std::size_t step=1, class F>
constexpr void for_each( F&& f, index_t<start> ={}, index_t<length> ={}, index_t<step> ={} ) {
  index_upto<length/step>()(
    foreacher([&](auto I){
      f( index_t<(I*step)+start>{} );
    })
  );
}

然后我们得到:

for_each<0, T>([](auto I) {
  std::cout << I << "n";
});

for_each([](auto I) {
  std::cout << I << "n";
}, index_t<0>{}, index_t<T>{});

使用用户定义的文字和模板变量可以进一步改善这一点:

template<std::size_t I>
constexpr index_t<I> index{};
template<char...cs>
constexpr auto operator""_idx() {
  return index< parse_value(cs...) >;
}

其中parse_valueconstexpr函数,该函数采用char...的序列并产生其无符号整数表示。