cal*_*rul 2 c++ stl-algorithm c++20 std-ranges
Planters我有一个包含 s 向量的类向量Plant。我的目标是返回一个植物向量,其中包含来自 Planter 1 的植物,然后是来自 Planter 2 的植物,依此类推。\n示例:planter{{1,2,3,4}, {2,3,4,5}}应该导致{1,2,3,4,2,3,4,5}. 请注意,数字代表植物对象。我试图用join_view它来压平它,但我收到了错误
error: class template argument deduction failed:\n 18 | plants = std::ranges::join_view(planterView);\n | ^\n/home/parallels/CMPT373/se-basic-cpp-template/lib/solutions/task05.cpp:18:52: error: no matching function for call to \xe2\x80\x98join_view(std::ranges::ref_view<std::vector<ex4::Planter> >&)\xe2\x80\x99\nRun Code Online (Sandbox Code Playgroud)\n我已经尝试过以下操作:
\nfor (auto it : planters){\n plants.insert(plants.end(), it.getPlants().begin(), it.getPlants().end());\n}\nRun Code Online (Sandbox Code Playgroud)\n这是可行的,但是我只允许使用一个循环(不包括 STL 函数调用内的循环)并且只能分配内存一次。上述方法多次分配内存。我该如何处理这个问题?
\n我的代码:
\nstd::vector<Plant> task05(std::vector<Planter> planters){\n std::vector<Plant> plants;\n auto planterView = std::views::all(planters);\n std::views::transform(planterView, [](Planter planter){ return planter.getPlants();});\n plants = ranges::views::all(std::ranges::join_view(planterView));\n return plants;\n}\nRun Code Online (Sandbox Code Playgroud)\n班级:
\nstruct Plant {\n int plantiness = 0;\n\n Plant(int plantiness)\n : plantiness{plantiness}\n { }\n\n bool\n operator==(const Plant& other) const noexcept {\n return plantiness == other.plantiness;\n }\n};\n\n\nclass Planter {\npublic:\n Planter(std::initializer_list<Plant> plants)\n : plants{plants}\n { }\n\n const std::vector<Plant>&\n getPlants() const noexcept {\n return plants;\n }\n\nprivate:\n std::vector<Plant> plants;\n};\nRun Code Online (Sandbox Code Playgroud)\n
std::vector<Plant> task05(std::vector<Planter> planters)
{
auto plants = planters
| std::views::transform([](Planter const& planter) -> decltype(auto) { return planter.getPlants();})
| std::views::join
| std::views::common
;
return std::vector<Plant>(plants.begin(), plants.end());
}
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/T75anE15c
首先你这里出错了
auto planterView = std::views::all(planters);
std::views::transform(planterView, [](Planter planter){ return planter.getPlants();});
Run Code Online (Sandbox Code Playgroud)
std::transformis inplace 但views::transform不是,并返回一个您忽略的视图,但这需要传递到join_view.
其次,begin 和 end 返回不同的类型,但是 的构造函数std::vector需要它们具有相同的类型,所以你必须使用views::common来实现这一点。
第三,推导的 lamdba 返回类型不会传播生成副本const&的性质。getPlants您已将返回类型声明为decltype(auto).
另外,您不需要打电话views::all。调用时会自动调用transform,您应该使用join适配器而不是join_view类型。
此外,范围在管道中使用时非常符合人体工程学,因此只编写一个跨越多行的表达式是最佳实践。
此外,没有太多的点包装int和std::vector<int>结构。只需使用std::tuple、std::array、std::variant、就很容易std::optional,而无需实际编写自己的类型。