给定constexpr std::array
和UnaryPredicate pred
,如何过滤数组以返回一个新的constexpr std::array
,其所有元素都符合pred(e)
?
struct foo {
int f1;
int f2;
};
static constexpr std::array<foo, 5> arr{ foo{1,1}, {2,2}, {3,3}, {4,4}, {5,5} };
int main() {
// will result in { foo{1,1}, {2,2}, {4,4}, {5,5} }
constexpr auto filterd = filter_array(arr, [](const foo& f) {return f.f1 != 3;})
return 0;
}
最佳答案
肯定是,依赖的类型(依赖于值的类型)在当今的C++中是不可能的。您不能仅通过函数参数来确定结果类型M
的大小std::array<T, M>
,这意味着M
必须是模板参数。
因此,您必须通过M
函数constexpr
为结果类型提供额外的模板参数count_if
,然后只需将每个元素确定为哪个值:
template<size_t I, typename T, typename Pred, std::enable_if_t<I == 0, int> = 0>
constexpr T get_element_helper(T const* arr, Pred&& pred){
return pred(arr[0]) ? arr[0] : get_element_helper<0>(arr + 1, pred);
}
template<size_t I, typename T, typename Pred, std::enable_if_t<I != 0, int> = 0>
constexpr T get_element_helper(T const* arr, Pred&& pred){
return pred(arr[0]) ? get_element_helper<I - 1>(arr + 1, pred) : get_element_helper<I>(arr + 1, pred);
}
template<typename T, size_t N, typename Pred, size_t ...Is>
constexpr std::array<T, sizeof...(Is)> filter_array_helper(std::array<T, N> const& arr, Pred&& pred, std::index_sequence<Is...>*){
return { get_element_helper<Is>(arr.data(), pred)... };
}
template<size_t M, typename T, size_t N, typename Pred>
constexpr std::array<T, M> filter_array(std::array<T, N> const& arr, Pred&& pred){
return filter_array_helper(arr, std::forward<Pred>(pred), (std::make_index_sequence<M>*)nullptr);
}
template<typename T, size_t N, typename Pred, size_t... Is>
constexpr size_t count_if_helper(std::array<T, N> const& arr, Pred&& pred, std::index_sequence<Is...>*){
return ((size_t)(bool)pred(arr[Is]) + ...);
}
template<typename T, size_t N, typename Pred>
constexpr size_t count_if(std::array<T, N> const& arr, Pred&& pred){
return count_if_helper(arr, std::forward<Pred>(pred), (std::make_index_sequence<N>*)nullptr);
};
int main(){
constexpr std::array<int, 5> a = { 0, 1, 2, 3, 4 };
constexpr auto pred = [](int a){ return a % 2 == 0; };
constexpr auto b = filter_array<count_if(a, pred)>(a, pred); // std::array<int, 3>{0, 2, 4}
}
关于c++ - 如何用 `std::array` lambda过滤constexpr `UnaryPredicate`?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64479759/