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...>();
}();
};
我有以下代码:
#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...>();
}();
};