@H_502_1@我有以下代码,我厌倦了编译器无法看到作为函数的参数传递的变量是constexpr的事实,所以我必须使用arity 0函数而不是1参数函数.
我知道这不是编译器错误,但我想知道是否有成语可以解决这个问题.
#include <array> #include <iostream> static constexpr std::array<int,5> arr{11,22,33,44,55}; template <typename C,typename P,typename Y> static constexpr void copy_if(const C& rng,P p,Y yi3ld) { for (const auto& elem: rng) { if (p(elem)){ yi3ld(elem); } } } // template<std::size_t N> static constexpr auto get_evens(/* const std::array<int,N>& arr */) { constexpr auto is_even = [](const int i) constexpr {return i % 2 == 0;}; constexpr int cnt = [/* &arr,*/&is_even]() constexpr { int cnt = 0; auto increment = [&cnt] (const auto&){cnt++;}; copy_if(arr,is_even,increment); return cnt; }(); std::array<int,cnt> result{}; int idx = 0; copy_if(arr,[&result,&idx](const auto& val){ result[idx++] = val;}); return result; } int main() { // constexpr std::array<int,55}; for (const int i:get_evens(/* arr */)) { std::cout << i << " " << std::endl; } }
如果我不想要的是什么:我想改变get_evens签名,使其在数组大小N上模板化,并且它需要一个类型为const std :: array< int,N>&的参数.
prog.cc:25:21: note: initializer of ‘cnt’ is not a constant expression
prog.cc:19:19: note: declared here
constexpr int cnt = [&arr,&is_even]()constexpr {
解决方法
#include <array> #include <iostream> static constexpr std::array<int,typename T> static constexpr void invoke_if(const C& rng,T target) { for (const auto& elem: rng) { if (p(elem)){ target(elem); } } } constexpr bool is_even(int i) { return i % 2 == 0; } template<std::size_t N> constexpr std::size_t count_evens(const std::array<int,N>& arr) { std::size_t cnt = 0; invoke_if(arr,[&cnt](auto&&){++cnt;}); return cnt; } template<std::size_t cnt,std::size_t N> static constexpr auto get_evens(const std::array<int,N>& arr) { std::array<int,cnt> result{}; int idx = 0; invoke_if(arr,55}; for (const int i:get_evens<count_evens(arr)>(arr)) { std::cout << i << " " << std::endl; } }
这works in g++,但在clang我们得到一个问题,因为begin
on an array
isn’t properly constexpr
with at least one library.或者可能g违反了标准,而clang没有.