我有一个类 Planters
的 vector ,其中包含 Plant
的 vector 。我的目标是返回一个植物 vector ,其中包含来自播种机 1 的植物,然后是来自播种机 2 的植物,等等。
示例: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:
18 | plants = std::ranges::join_view(planterView);
| ^
/home/parallels/CMPT373/se-basic-cpp-template/lib/solutions/task05.cpp:18:52: error: no matching function for call to ‘join_view(std::ranges::ref_view<std::vector<ex4::Planter> >&)’
我尝试了以下方法:
for (auto it : planters){
plants.insert(plants.end(), it.getPlants().begin(), it.getPlants().end());
}
这有效,但是我只被允许使用一个循环(不包括 STL 函数调用中的循环)并且只能分配一次内存。上述方法多次分配内存。我该如何处理?
我的代码:
std::vector<Plant> task05(std::vector<Planter> planters){
std::vector<Plant> plants;
auto planterView = std::views::all(planters);
std::views::transform(planterView, [](Planter planter){ return planter.getPlants();});
plants = ranges::views::all(std::ranges::join_view(planterView));
return plants;
}
类:
struct Plant {
int plantiness = 0;
Plant(int plantiness)
: plantiness{plantiness}
{ }
bool
operator==(const Plant& other) const noexcept {
return plantiness == other.plantiness;
}
};
class Planter {
public:
Planter(std::initializer_list<Plant> plants)
: plants{plants}
{ }
const std::vector<Plant>&
getPlants() const noexcept {
return plants;
}
private:
std::vector<Plant> plants;
};
最佳答案
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());
}
https://godbolt.org/z/T75anE15c
首先你错在这里
auto planterView = std::views::all(planters);
std::views::transform(planterView, [](Planter planter){ return planter.getPlants();});
std::transform
就位但views::transform
不是并返回一个您忽略的 View ,但这需要传递到 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
永远不要真正编写自己的类型。
关于c++ - 包含结构 vector 的类的展平 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74077309/