【问题标题】:Using for_each with std::unique_ptr将 for_each 与 std::unique_ptr 一起使用
【发布时间】:2017-05-22 22:11:02
【问题描述】:

当我尝试将 for_each 算法与 std::unique_ptr 一起使用时,我遇到了以下错误。我在下面的 profile.h 部分放大了它。

奇怪的是,如果我将其更改为 std::shared_ptr,我能够编译,我怀疑它按值获取容器的元素,因此不喜欢引用 unique_ptrs。但是,我希望它是 unique_ptr 理想情况下,因为这些任务应该放在 ToRun_ 容器内,并在任务执行后移至 Completed_ 容器,所以 shared_ptr 在这里对我没有任何好处。

我得到的错误是:

没有匹配函数调用类型为“(Profile.cpp:429:54 的lambda)”的对象

__f(*__first);

指的是这行代码:

for_each(ToRun_.begin(), ToRun_.end(), [&os](std::unique_ptr<Task>& e){
  if (e){
    os << e->getName() <<'\n';
  }
});

在我将它转换为使用智能指针之前,我使用了原始指针,我可以保证e-&gt;getName() 100% 有效。我的困惑是为什么它在这种情况下不起作用?我该怎么做才能让它正常工作?

个人资料.h

#include <algorithm>
#include <vector>
#include <map>
#include <iostream>
#include "Task.h"
#include "Global.h" //Where my user defined global functions go

class Profile{
  std::vector<std::unique_ptr<Task>>ToRun_;
  std::vector<std::unique_ptr<Task>>Completed_;
  std::vector<std::string>menu_;
  //Ownership of ofstream object
  std::ofstream& of_;
public:
  Profile (const char* filename, std::ofstream& os, ARAIG_sensors& as);
  virtual ~Profile();
  void run();
  //Executes specified number of tasks user specifies
  void execute (unsigned long tasks);
  void load_menu();
  long show_menu()const;
  long getInput(std::string prompt, int min, long max, menuOption option = NONE);
  //Display all tasks to the screen
  std::ostream& display_todo_tasks (std::ostream& os) const;
  //Display completed tasks to the screen
  std::ostream& display_completed_tasks (std::ostream& os)const;
  //Display next task to the screen
  std::ostream& display_next_task (std::ostream& os) const;
  //Display last completed task
  std::ostream& display_last_task(std::ostream& os)const;
};

配置文件.cpp

std::ostream& Profile::display_todo_tasks(std::ostream& os)const{
  //Display all tasks in ToRun container
  if(ToRun_.size() > 0){
    new_line(user_interface_skip_screen);
    std::cout << "\nTasks to be completed\n";
    print_dash(29);
    for_each(ToRun_.begin(), ToRun_.end(), [&os](std::unique_ptr<Task>& e){
      if (e){
        os << e->getName() <<'\n';
      }
    });
    new_line(user_interface_system_message_skip_line - 1);
  }else{
    std::cerr << "There are no tasks to be performed in the task list.";
    std::cerr.flush();
    new_line(user_interface_system_message_skip_line);
  }
  return os;
}

【问题讨论】:

  • 顺便说一句,你有什么理由不只是使用基于范围的for 而不是for_each
  • 当我在谷歌上搜索试图学习 C++ 时,我在某处读到,最好使用算法而不是代表或基于范围的 for 循环。我也被告知它更有效,因此使用它。我实际上并不确定什么时候使用什么,并且过去我对 std::accumulate 的意外行为感到沮丧。
  • 在您看来for(const auto&amp; e : ToRun_) 是否比std::for_each(ToRun_.begin(), ToRun_.end(), [&amp;os](std::unique_ptr&lt;Task&gt;&amp; e) 更糟糕?该声明的目的是建议在适当时使用算法。也就是说,在搜索时不要使用基于范围的for,因为std::find 可以做到这一点。如果适合您问题的算法是std::for_each,请不要打扰。

标签: c++ algorithm c++11 lambda unique-ptr


【解决方案1】:
std::ostream& Profile::display_todo_tasks(std::ostream& os)const

您的函数是const 函数。因此,ToRun_ 是一个 const 对象。因此,您从beginend 获得的迭代器是const_iterators。因此,当您取消引用它们时,您得到的是 const 引用

您的 lambda 采用非const 引用。因此不兼容。让它引用const,应该没问题。

【讨论】:

  • 就是这样!感谢您的帮助。
  • 验证答案@geekster01 怎么样?
猜你喜欢
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 2011-06-05
  • 1970-01-01
  • 2021-05-02
相关资源
最近更新 更多