Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a std::lock_guard without violating const correctness?

In a subclass, I have a private std::mutex m field that I use in an implementation of a base class pure virtual method to return a value in a thread-safe way (the value can be updated by another thread):

int SubClass::get() const // implements 'virtual int get() = 0 const' of the base class
{            
    std::lock_guard<std::mutex> lck(m); 
    return value;
}

The compiler is telling me that this violates const correctness by producing an error:

error: binding 'const std::mutex' to reference of type 'std::lock_guard::mutex_type& {aka std::mutex&}' discards qualifiers

Is there a way to make this compliant and use std::lock_guard in a const-correct way? Simply changing it to const std::lock_guard changes nothing. I don't really understand which part is problematic, then again I'm quite new to C++ ...

like image 723
w128 Avatar asked Jan 07 '18 00:01

w128


1 Answers

The this pointer is implicitly const (it's actually an rvalue of type const SubClass *), so any member you are accessing are const implicitly.

If you could modify member object in a const function, then what would be the point of const? :)

The lock guard wants to modify the mutex, to lock and unlock it, but because it is const, it cannot, that is the problem. It doesn't matter if the lock guard is const or not, because that has nothing to do with the ability of the lock guard to modify the mutex or not.

To effectively solve this problem, there is a keyword you can use to mark member objects that can be modified in const qualified functions. Now obviously, you shouldn't abuse this feature and mark every object of your class with it:

class SubClass {
/*...*/
private:
    mutable std::mutex m;
  //^^^^^^^
/*...*/
}; 
like image 72
Rakete1111 Avatar answered Oct 30 '22 16:10

Rakete1111