【问题标题】:std::optional taking non-copyable?std::optional 不可复制?
【发布时间】:2020-02-28 12:51:53
【问题描述】:

假设我有类似于这个伪代码的东西:

std::optional<std::pair<double*, std::scope_lock<std::mutex> > > getDataTogetherWithLock() {
  if (!some_ptr) {
    return std::nullopt;
  }
  return some_ptr->getDataTogetherWithLock();//just returns std::pair<double*, std::scope_lock<std::mutex> >
}

这行不通,基本上如果用真实代码尝试会报返回类型不能转换为std::optional的错误。

解决这个难题的最佳方法是什么?

【问题讨论】:

  • 您特别说不可复制。但这可能是移动更合适的情况。
  • @MSalters 我会说搬家很好 - 但如何?
  • 同意 - 如果您对移动感到满意,请发布一个最小示例。当然不必编译,但它不应该编译,因为与您的实际示例完全相同的错误。

标签: c++ c++17 noncopyable stdoptional


【解决方案1】:

问题是std::scoped_lock 本身既不能移动也不能复制。因此,成员函数的返回值无法复制/移动到您发布的函数的返回值中。修复很简单。使用可移动的std::unique_lock。在 gcc 上为我编译的以下测试代码

#include <optional>
#include <mutex>

struct A {
    std::pair<double*, std::unique_lock<std::mutex> > getDataTogetherWithLock();
} *some_ptr;

std::optional<std::pair<double*, std::unique_lock<std::mutex> > > getDataTogetherWithLock() {
  if (!some_ptr) {
    return std::nullopt;
  }
  return some_ptr->getDataTogetherWithLock();
}

使用std::scoped_lock 将无法编译。

【讨论】:

  • @darune 不符合 cppreference 或 gcc 主干。
  • @darune:不,它有一个已删除的复制 ctor 并且没有移动 ctor。那是故意的。顾名思义,它是块作用域锁。
  • @MSalters 你确定它没有作为默认实现。 ,似乎在我这边编译并且在逻辑上似乎可以(我认为)围绕锁移动
  • @darune:我不熟悉每个实现。我同意 patatahooligan,unique_lock 是更便携的解决方案。
  • @darune 见here。如果存在用户定义的复制构造函数,则没有隐式声明的移动构造函数。因此,您的 OP 中的代码尝试使用已删除的复制构造函数。如果某些代码看起来像移动了已编译的锁,则很可能是保证复制省略或非标准行为的情况。
猜你喜欢
  • 2018-08-06
  • 2017-05-14
  • 2013-05-09
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
相关资源
最近更新 更多