C++ 模板:有点像无限递归,但不是真的

C++ Template: Kind of like infinite recursion but not really

我有以下代码:

#include <cstdint>

template <uint32_t test_value, uint32_t ...Vn>
struct is_prime_tmpl;

template <uint32_t test_value>
struct is_prime_tmpl<test_value> {
    static constexpr bool value = true;
};

template <uint32_t test_value, uint32_t V1, uint32_t ...Vn>
struct is_prime_tmpl<test_value, V1, Vn...> {
    static constexpr bool value = (test_value % V1 != 0) && is_prime_tmpl<test_value, Vn...>::value;
};

template <uint32_t ...Vn>
struct prime {};

template <uint32_t max_target, uint32_t test_value, class PrimeList>
struct generate_prime_helper_tmpl;

template <uint32_t max_target, uint32_t test_value, uint32_t ...Vn>
struct generate_prime_helper_tmpl<max_target, test_value, prime<Vn...>> {
    static constexpr auto result = test_value <= max_target ? 
            (is_prime_tmpl<test_value, Vn...>::value ? 
                generate_prime_helper_tmpl<max_target, test_value + 1, prime<Vn..., test_value>>::result :                  generate_prime_helper_tmpl<max_target, test_value + 1, prime<Vn...>>::result) :
            prime<Vn...>();
};

int main() {
    static_assert(is_prime_tmpl<2>::value);
    static_assert(std::is_same_v<generate_prime_helper_tmpl<2, 2, prime<>>::result, prime<2>);
}

代码正在尝试生成一个素数序列。但是它无法在我的本地机器上用 g++10 编译。编译器不会发出任何警告或错误。它只是永远编译。

递归似乎以某种方式被破坏了。但我看不到它。与实际解决方案相比,我对问题出在哪里更感兴趣。

知道哪里出了问题吗?

您的三元运算符不会停止递归,这会使您的代码陷入无限递归。当参数不满足条件时,你应该使用if constexpr来防止递归。

像这样:

template <uint32_t max_target, uint32_t test_value, uint32_t ...Vn>
struct generate_prime_helper_tmpl<max_target, test_value, prime<Vn...>> {
  static constexpr auto result = [] {
    if constexpr (test_value <= max_target) {
      if constexpr (is_prime_tmpl<test_value, Vn...>::value)
        return generate_prime_helper_tmpl<max_target, test_value + 1, prime<Vn..., test_value>>::result;
      else
        return generate_prime_helper_tmpl<max_target, test_value + 1, prime<Vn...>>::result;
    }
    else
      return prime<Vn...>();
  }();
};

Demo.