如何在C++编译时应用if

Amm*_*ain 11 c++ templates template-meta-programming

我试图编写一个通用static_for实现,可以接受边界,增量函数和比较函数来运行循环.我一直在使用这个构造,其中简单的循环增加1.在这种情况下,通过简单地专注于IDX & END相等而很容易停止循环展开.

但是,当增量可以是任意整数时,不能保证IDX & END总是相等.该if条件仅在运行时计算.在下面的代码片段中,我试图专注于std::false_type停止递归.通过评估std::less函数(可以由用户替换任何其他评估)来构造integral_constant .不幸的是,此comparator功能也仅在运行时进行评估,因此编译器失败.有人可以建议如何使这个工作?

注意:使用C++ 11.

template <int idx, int end, typename eval, int count, typename comparator>
struct static_for_loop {
  template <typename Lambda, typename... Args>
  void operator()(const Lambda& function, Args... args) const {
    if (comparator()(idx, end)) {
      std::integral_constant<int, idx> i;

      function(i, args...);

      constexpr bool lesser = comparator()(idx + count, end);
      static_for_loop<idx + count, end, std::integral_constant<bool, lesser>, count,
                      comparator>()(function, args...);
    }
  }
};

template <int idx, int end, int count, typename comparator>
struct static_for_loop<idx, end, std::false_type, count, comparator> {
  template <typename Lambda, typename... Args>
  void operator()(const Lambda& function, Args... args) const {}
};

template <int idx, int end, int count = 1, typename comparator = std::less<int>>
struct static_for {
  template <typename Lambda, typename... Args>
  void operator()(const Lambda& function, Args... args) const {
    static_for_loop<idx, end, std::true_type, count, comparator>()(function, args...);
  }
};
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 4

我发现将所有内容包装在一个对象中更容易:

template <int S, int E, int step>
struct iter {
    auto next() { return iter<std::min(E, S+step), E, step>{}; }
};
Run Code Online (Sandbox Code Playgroud)

然后,对于完成的情况和未完成的情况,您都会有一个重载:

template <int S, int E, int step, class F, class... Args>
void for_loop(iter<S, E, step> i, F func, Args... args) {
    func(S, args...);

    for_loop(i.next(), func, args...);
}

template <int E, int step, class F, class... Args>
void for_loop(iter<E, E, step>, F, Args... ) {
}
Run Code Online (Sandbox Code Playgroud)

例如:

// prints 0 4 8
for_loop(iter<0, 10, 4>{}, [](int i){std::cout << i << ' ';});   
Run Code Online (Sandbox Code Playgroud)

或者,可以用来enable_if区分情况以避免需要min

template <int S, int E, int step, class F, class... Args>
std::enable_if_t<(S<E)> for_loop(iter<S, E, step>, F func, Args... args)
{
    func(S, args...);
    for_loop(iter<S+step, E, step>{}, func, args...);
}

template <int S, int E, int step, class F, class... Args>
std::enable_if_t<!(S<E)> for_loop(iter<S, E, step>, F , Args... )
{
}
Run Code Online (Sandbox Code Playgroud)

YMMV 你喜欢哪一个。