Home > Mobile >  C Template: Kind of like infinite recursion but not really
C Template: Kind of like infinite recursion but not really

Time:11-11

I have the following code:

#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>);
}

The code is trying to generate a sequence of prime numbers. But it fails to compile on my local machine with g 10. The compiler doesn't emit any warning nor error. It just compiles forever.

It seems like the recursion is broken somehow. But I fail to see it. I am more interested in what goes wrong than the actual solution.

Any idea what has gone wrong?

CodePudding user response:

Your ternary operator does not stop recursion, which makes your code fall into infinite recursion. You should use if constexpr to prevent recursion when the argument does not meet the condition.

Something like this:

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.

  • Related