LouisCharlesC / safe

Header only read/write wrapper to combine mutexes with locks.
MIT License
149 stars 11 forks source link

Why is the access class not movable? #10

Closed diegohavenstein closed 5 years ago

diegohavenstein commented 5 years ago

I would like to create accessors with a helper. This will not work because Access class is not movable

template <typename T, typename... AccessArgs> auto read(safe::Lockable<T> const& obj, AccessArgs&&... accessArgs) { return std::move(safe::ReadAccess<safe::Lockable<T>>{obj, std::forward<AccessArgs> accessArgs)...}); }

Is there any particular reason not to have this?

LouisCharlesC commented 5 years ago

Access (with default template parameter) is not movable because std::lock_guard is not movable. The default Access class has a member std::lock_guard variable, which makes it also not movable. To make the Access class movable, you can use std::unique_lock instead if you don't mind.

There's an issue with the code you posted: it returns an rvalue reference to a temporary. As a general rule, you should not std::move something out of a function.

To get what you want, I see three possibilities.

  1. switch to C++17. Rules for temporaries creation changed in C++17 which means you can return non-movable objects.
  2. Return the Access object by list-initialization, and capture the return value by rvalue reference. Have a look at the readAccess() member function from safe::Safe for an example of return by list-initialization, and capturing by rvalue reference simply means calling your read() function like this: auto&& access = read(safe);
  3. As I said, use std::unique_lock instead of std::lock_guard.

Cheers!

diegohavenstein commented 5 years ago

Thanks!