Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用'UnaryPredicate'lambda'筛选constexpr'std::array'?_C++_Templates_C++17_Constexpr - Fatal编程技术网

C++ 如何使用'UnaryPredicate'lambda'筛选constexpr'std::array'?

C++ 如何使用'UnaryPredicate'lambda'筛选constexpr'std::array'?,c++,templates,c++17,constexpr,C++,Templates,C++17,Constexpr,给定一个constepr std::array和一个UnaryPredicate pred,我如何筛选数组以返回一个新的constepr std::array,它的所有元素都满足pred(e) structfoo{ int f1; int f2; }; 静态constexpr std::数组arr{foo{1,1},{2,2},{3,3},{4,4},{5,5}; int main(){ //将导致{foo{1,1}、{2,2}、{4,4}、{5,5} constexpr auto filter

给定一个
constepr std::array
和一个
UnaryPredicate pred
,我如何筛选数组以返回一个新的
constepr std::array
,它的所有元素都满足
pred(e)

structfoo{
int f1;
int f2;
};
静态constexpr std::数组arr{foo{1,1},{2,2},{3,3},{4,4},{5,5};
int main(){
//将导致{foo{1,1}、{2,2}、{4,4}、{5,5}
constexpr auto filterd=filter_数组(arr,[](const foo&f){返回f.f1!=3;})
返回0;
}

< /代码> 这肯定是,<强>依赖类型< /强>,在当前C++中,依赖于<强>值<强>的类型是不可能的。您不能仅通过函数参数来决定结果类型
std::array
的大小
M
,这意味着
M
必须是模板参数

因此,您必须通过
constepr
函数
count\u if
为结果类型提供一个额外的模板参数
M
,然后确定每个元素的值:

模板
constexpr T get_element_helper(T const*arr、Pred和&Pred){
return pred(arr[0])?arr[0]:获取元素辅助对象(arr+1,pred);
}
模板
constexpr T get_element_helper(T const*arr、Pred和&Pred){
返回pred(arr[0])?获取元素辅助对象(arr+1,pred):获取元素辅助对象(arr+1,pred);
}
模板
constexpr std::数组过滤器\u数组\u辅助程序(std::数组const&arr、Pred&Pred、std::索引\u序列*){
返回{get_element_helper(arr.data(),pred)…};
}
模板
constepr std::数组过滤器\u数组(std::数组const&arr、Pred&Pred){
返回过滤器\数组\助手(arr,std::forward(pred),(std::make\ u index \ u sequence*)nullptr);
}
模板
constexpr size\u t count\u if\u helper(std::array const&arr,Pred&Pred,std::index\u sequence*){
返回((大小)(bool)pred(arr[Is])+…);
}
模板
constexpr size\u t count\u if(标准::数组const&arr、Pred&Pred){
如果帮助器(arr,std::forward(pred),(std::make_index_sequence*)nullptr)返回计数;
};
int main(){
constexpr std::数组a={0,1,2,3,4};
constexpr auto pred=[](int a){返回一个%2==0;};
constexpr auto b=filter_array(a,pred);//std::array{0,2,4}
}

因为
中有很多算法,所以
get\u元素\u助手是我缺少的,非常聪明!顺便说一句,c++17允许在constexpr函数中使用局部变量和for循环,
count\u如果
实际上可以在单个函数中实现。@zoujyjs你说得对。只是我已经习惯了。无论如何,感谢C++17!你会使用c++20吗?由于许多算法,如
std::remove_if
现在是
constepr
。但是
arr
是常量,不能修改,只能生成一个新数组。我尝试了
remove\u if
并且编译器抱怨“您无法分配一个常量变量”`No,我们可以在lambda中复制
arr
并修改它,然后使用
constepr std::pair
接受修改后的
arr
,并对应大小,但是gcc-10的当前版本也有一些。是的,汇编代码确实编译成了期望的结果。在我的情况下使用它有点激进,因为它甚至没有在最新的msvc 2019中编译。无论如何,这有助于使用最先进的标准。
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;
}
#include <algorithm>
#include <array>    

struct foo {
  int f1;
  int f2;
  bool operator==(const foo&) const = default;
};

constexpr static std::array arr{foo{1,1}, foo{2,2}, foo{3,3}, foo{4,4}, foo{5,5}};

constexpr auto filter_array(auto pred) {
  constexpr auto p = [=] {
    auto res = arr;
    auto size = std::distance(res.begin(), std::remove_if(res.begin(), res.end(), pred));
    return std::pair{res, size};
  }();
  constexpr auto res = p.first;
  constexpr auto size = p.second;
  return [=]<auto... Is>(std::index_sequence<Is...>) {
    return std::array{res[Is]...};
  }(std::make_index_sequence<size>{});
}

int main() {
  // will result in { foo{1,1}, {2,2}, {4,4}, {5,5} }
  constexpr auto filterd = filter_array([](const foo& f) { return f.f1 == 3; });
  static_assert(filterd == std::array{foo{1,1}, foo{2,2}, foo{4,4}, foo{5,5}});
}