如何检测std::integer_sequence中特定数字的索引?
How to detect index of a specific number in a std::integer_sequence?
我基本上使用这个问题作为参考起草了编译时素数检查:
Compile time prime checking
我有可用的 IsPrime<3>::value。
我想设计一个查找元函数,它基本上可以在编译时识别我的整数序列中是否有素数,如果有则 returns 索引 else returns -1;
例子
find<std::integer_sequence<4,6,8,3>>::value // 3
find<std::integer_sequence<4,6,8,27>>::value // -1
find<std::integer_sequence<4,6,8,3,5,27>>::value // 3(as index 3 is the first prime, we do not care about others)
我无法全神贯注于参数包,任何好的例子或适当的解释解决方案都会有很大帮助。
大声思考如下内容,但无法全神贯注,如何获取索引以及如何在找到序列中的第一个素数后停止迭代
template<typename T... args>
struct find_prime{
static constexpr int value = is_prime<args>::value ? increement++ : is_prime<...>::args;
};
抱歉,如果这听起来像一个愚蠢的方法,无法弄清楚如何使用索引进行迭代
这里是一个 example,代码少得多:
template <int ...Ints>
constexpr int find_prime() {
constexpr auto res = fp<Ints...>(std::make_index_sequence<sizeof...(Ints)>{});
return (res == sizeof...(Ints)) ? -1 : res;
}
template <int ...Ints, auto ...Indices>
constexpr int fp(std::index_sequence<Indices...>) {
return std::min({ (is_prime(Ints) ? Indices : sizeof...(Indices))... });
}
这个想法是将每个数字绑定到它在列表中的索引,并且只是 return 列表中作为质数的最小索引。如果索引列表中的所有条目都是列表本身的长度,则程序应 return -1.
这可以通过递归模板来完成。当找到质数时,递归提前终止。
// Base failure case: our list is empty (or the specialization below would match)
template <int, int...>
struct find_prime_impl {
static constexpr int value = -1;
};
// Specialization for at least one item remaining. If it's prime, the current
// index is assigned to value; otherwise we recurse with an incremented index,
// and without the first item.
template <int Index, int Head, int... Tail>
struct find_prime_impl<Index, Head, Tail...> {
static constexpr int value = [] {
if constexpr (is_prime<Head>::value) {
return Index;
} else {
return find_prime_impl<Index + 1, Tail...>::value;
}
}();
};
// Calls the recursive template with the initial index 0.
template <int... Values>
struct find_prime : find_prime_impl<0, Values...> {};
immediately-invoked lambda 允许我们使用 if constexpr
,这意味着编译器可以在满足终止情况时跳过实例化 find_prime_impl
的递归使用。三元运算符不会以这种方式“short-circuit”实例化,并且仍会实例化整个递归链一直到 find_prime_impl<Index>
.
(Demo)
要直接使用 std::integer_sequence
,调整实现以使其符合预期:
// Failure case when the type isn't std::integer_sequence
template <int, typename>
struct find_prime_impl {};
// Failure case when our list is empty (or the specialization below would match)
template <typename TInt, int Index>
struct find_prime_impl<Index, std::integer_sequence<TInt>> {
static constexpr int value = -1;
};
// Specialization for at least one item remaining. If it's prime, the current
// index is assigned to value; otherwise we recurse with an incremented index,
// and without the first item.
template <typename TInt, int Index, TInt Head, TInt... Tail>
struct find_prime_impl<Index, std::integer_sequence<TInt, Head, Tail...>> {
static constexpr int value = [] {
if constexpr (is_prime<Head>::value) {
return Index;
} else {
return find_prime_impl<
Index + 1,
std::integer_sequence<TInt, Tail...>
>::value;
}
}();
};
// Calls the recursive template with the initial index 0.
template <typename T>
struct find_prime : find_prime_impl<0, T> {};
我基本上使用这个问题作为参考起草了编译时素数检查: Compile time prime checking
我有可用的 IsPrime<3>::value。
我想设计一个查找元函数,它基本上可以在编译时识别我的整数序列中是否有素数,如果有则 returns 索引 else returns -1;
例子
find<std::integer_sequence<4,6,8,3>>::value // 3
find<std::integer_sequence<4,6,8,27>>::value // -1
find<std::integer_sequence<4,6,8,3,5,27>>::value // 3(as index 3 is the first prime, we do not care about others)
我无法全神贯注于参数包,任何好的例子或适当的解释解决方案都会有很大帮助。
大声思考如下内容,但无法全神贯注,如何获取索引以及如何在找到序列中的第一个素数后停止迭代
template<typename T... args>
struct find_prime{
static constexpr int value = is_prime<args>::value ? increement++ : is_prime<...>::args;
};
抱歉,如果这听起来像一个愚蠢的方法,无法弄清楚如何使用索引进行迭代
这里是一个 example,代码少得多:
template <int ...Ints>
constexpr int find_prime() {
constexpr auto res = fp<Ints...>(std::make_index_sequence<sizeof...(Ints)>{});
return (res == sizeof...(Ints)) ? -1 : res;
}
template <int ...Ints, auto ...Indices>
constexpr int fp(std::index_sequence<Indices...>) {
return std::min({ (is_prime(Ints) ? Indices : sizeof...(Indices))... });
}
这个想法是将每个数字绑定到它在列表中的索引,并且只是 return 列表中作为质数的最小索引。如果索引列表中的所有条目都是列表本身的长度,则程序应 return -1.
这可以通过递归模板来完成。当找到质数时,递归提前终止。
// Base failure case: our list is empty (or the specialization below would match)
template <int, int...>
struct find_prime_impl {
static constexpr int value = -1;
};
// Specialization for at least one item remaining. If it's prime, the current
// index is assigned to value; otherwise we recurse with an incremented index,
// and without the first item.
template <int Index, int Head, int... Tail>
struct find_prime_impl<Index, Head, Tail...> {
static constexpr int value = [] {
if constexpr (is_prime<Head>::value) {
return Index;
} else {
return find_prime_impl<Index + 1, Tail...>::value;
}
}();
};
// Calls the recursive template with the initial index 0.
template <int... Values>
struct find_prime : find_prime_impl<0, Values...> {};
immediately-invoked lambda 允许我们使用 if constexpr
,这意味着编译器可以在满足终止情况时跳过实例化 find_prime_impl
的递归使用。三元运算符不会以这种方式“short-circuit”实例化,并且仍会实例化整个递归链一直到 find_prime_impl<Index>
.
(Demo)
要直接使用 std::integer_sequence
,调整实现以使其符合预期:
// Failure case when the type isn't std::integer_sequence
template <int, typename>
struct find_prime_impl {};
// Failure case when our list is empty (or the specialization below would match)
template <typename TInt, int Index>
struct find_prime_impl<Index, std::integer_sequence<TInt>> {
static constexpr int value = -1;
};
// Specialization for at least one item remaining. If it's prime, the current
// index is assigned to value; otherwise we recurse with an incremented index,
// and without the first item.
template <typename TInt, int Index, TInt Head, TInt... Tail>
struct find_prime_impl<Index, std::integer_sequence<TInt, Head, Tail...>> {
static constexpr int value = [] {
if constexpr (is_prime<Head>::value) {
return Index;
} else {
return find_prime_impl<
Index + 1,
std::integer_sequence<TInt, Tail...>
>::value;
}
}();
};
// Calls the recursive template with the initial index 0.
template <typename T>
struct find_prime : find_prime_impl<0, T> {};