给定constexpr std::arrayUnaryPredicate 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/

10-17 00:00