c++c++17noncopyablestdoptional

std::optional taking non-copyable?


Suppose i have something akin to this pseudocode:

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> >
}

This won't work, basicly if tried with real code will give an error about the return type cannot be converted to std::optional.

What's the best way to solve this conundrum ?


Solution

  • The problem is that std::scoped_lock itself is neither movable nor copyable. So the return value of the member function cannot be copied/moved into the return value of the function you posted. The fix is simple. Use an std::unique_lock that is moveable. The following test code compiled for me on 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();
    }
    

    With std::scoped_lock it would fail to compile.