c++ - 包含结构 vector 的类的展平 vector

标签 c++ c++20 stl-algorithm std-ranges

我有一个类 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类型。

此外,范围在管道中使用时非常符合人体工程学,因此最好只编写一个跨多行的表达式。

此外,没有太多要点环绕 intstd::vector<int>在结构中。很容易使用 std::tuple , std::array , std::variant , std::optional永远不要真正编写自己的类型。

关于c++ - 包含结构 vector 的类的展平 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74077309/

相关文章:

c++ - 如何访问兼容的 std::variant 变体?

c++ - 将 std::atomic 与 futex 系统调用一起使用

c++ - std::transform 和 std::for_each 有什么区别?

c++ - 为什么 std::find_if(first, last, p) 不通过引用获取谓词?

c++ - Gtk 和 gstreamer 链接器错误

c++ - 将二维矩阵解析为链表

c++ - C++17/C++2a 编译时的哈希类型

c++ - 是否有计算 vector 中所有正数的函数?

c++ - Windows CMD 无法正确输出 UTF-16

c++ - 为什么我们确实需要构造函数?