I have a base class with a mutex since all inheriting classes need the ability to lock state. I want to force all children copy and assignment constructors to lock the mutex, ideally without having to specify so manually in the child implementation.
So far I came up with this pattern which encapsulates all deepcopy actions of a child in a separate virtual method, hereby also reminding child implementations that deep copy operations need to be taken care of:
#include <iostream>
#include <mutex>
template<typename T>
class baseclass {
public:
mutable std::mutex mtx;
// forcing children to implement a copy method
virtual void child_copy(T const& other)=0;
baseclass<T>()=default;
// Copy constructor
baseclass<T>(baseclass<T> const& other){
std::unique_lock<std::mutex> lock_other(other.mtx);
copy_from(other);
}
// copy assignment operator
baseclass& operator=(baseclass const& other) {
if (&other != this) {
std::unique_lock<std::mutex> lock_this(mtx, std::defer_lock);
std::unique_lock<std::mutex> lock_other(other.mtx, std::defer_lock);
std::lock(lock_this, lock_other);
copy_from(other);
}
return *this;
}
private:
void copy_from(baseclass const& other) {
std::cout<<"calling copy_from"<<std::endl;
static_cast<T*>(this)->child_copy(static_cast<T const&>(other));
std::cout<<"done calling copy_from"<<std::endl;
}
};
class Implementation : public baseclass<Implementation>{
public:
int state{};
void child_copy(Implementation const& other) override{
std::cout<<"calling child_copy"<<std::endl;
state = other.state;
}
};
int main(){
Implementation A;
Implementation B(A); // ERROR HERE
}
However I'm getting an error: "libc++abi: Pure virtual function called!". It appears that static_cast<T*>(this)->child_copy(static_cast<T const&>(other)) is causing the error.
Is there a working way to enforce the desired pattern?