Below is minimal code to reproduce the error.
#include <iostream>
#include <mutex>
#include <vector>
class A {
std::mutex mutex;
public:
A(){};
};
int main()
{
std::vector<std::pair<std::string,A>> aa;
A a;
//aa.push_back(std::make_pair(std::string("aa"),A()));
//aa.push_back(std::make_pair(std::string("aa"),a));
aa.push_back(std::make_pair(std::string("aa"),std::move(a)));
}
Below is error.
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27026.1 for x64 Copyright (C) Microsoft Corporation. All rights reserved.
> C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\xlocale(319):
> warning C4530: C++ exception handler used, but unwind semantics are
> not enabled. Specify /EHsc C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\utility(405):
> error C2440: '<function-style-cast>': cannot convert from 'initializer
> list' to '_Mypair' C:\Program Files (x86)\Microsoft Visual
> Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\utility(405):
> note: No constructor could take the source type, or constructor
> overload resolution was ambiguous
> ..\examples\json_object\json.cpp(16): note: see reference to function
> template instantiation 'std::pair<std::string,A>
> std::make_pair<std::string,A>(_Ty1 &&,_Ty2 &&)' being compiled with
> [
> _Ty1=std::string,
> _Ty2=A ]
Similar error for gcc
compiler.
When I remove std::mutex
from class OR don't push the object on std::vector
, then it compiles fine.
As per the documentation on std::mutex
.
std::mutex
is neither copyable nor movable.
Since class A
contains a std::mutex
variable mutex
, it is not movable either.
As P.W. pointed out, std::mutex
is neither copyable nor movable, and for good reason. The whole point of having a mutex is to protect against simultaneous multithreaded access to some data. The move operation itself needs to be protected, and the mutex should be used by the move operation.
The following example gives the class some movable data and shows how the mutex should be used in a move operation (copy operations would be similar):
#include <iostream>
#include <mutex>
#include <vector>
#include <memory>
class A {
public:
A() {};
// Move constructor
A(A&& other) {
std::lock_guard<std::mutex> guard(other.m_mutex);
m_data = std::move(other.m_data);
}
// Move operator
A& operator=(A&& other) {
if (this == &other) return *this;
// Lock this and other in a consistent order to prevent deadlock
std::mutex* first;
std::mutex* second;
if (this < &other) {
first = &this->m_mutex;
second = &other.m_mutex;
} else {
first = &other.m_mutex;
second = &this->m_mutex;
}
std::lock_guard<std::mutex> guard1(*first);
std::lock_guard<std::mutex> guard2(*second);
// Now both this and other are safe to access. Do the actual data move.
m_data = std::move(other.m_data);
return *this;
}
private:
std::mutex m_mutex;
std::unique_ptr<int> m_data;
};
int main() {
std::vector<std::pair<std::string,A>> aa;
A a1;
A a2;
a1 = std::move(a2);
aa.emplace_back("aa", std::move(a1));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With