template<class Key, class Value>
class ThreadSafeMap
{
std::mutex m_;
std::map<Key, Value> c_;
public:
Value get(Key const& k) {
std::unique_lock<decltype(m_)> lock(m_);
return c_[k]; // Return a copy.
}
template<class Value2>
void set(Key const& k, Value2&& v) {
std::unique_lock<decltype(m_)> lock(m_);
c_[k] = std::forward<Value2>(v);
}
};
Thread safe std::map: Locking the entire map and individual values
I just read the link above and found the piece of code. It looks great with it to make a thread-safe map. I understand that in the function set
, we used the reference collapsing rules on the second parameter v
. But I don't understand why we need import another template<class Value2>
, why can't we simply use the existing template class Value
?
v
is supposed to be declared as forwarding reference, which only works with templates. Then we need make set
itself template.
(emphasis mine)
Forwarding references are a special kind of references that preserve the value category of a function argument, making it possible to forward it by means of std::forward. Forwarding references are either:
- function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template:
If we declare set
as a non-template as:
template<class Key, class Value>
class ThreadSafeMap
{
...
// non-template member function
void set(Key const& k, Value&& v) {
std::unique_lock<decltype(m_)> lock(m_);
c_[k] = std::forward<Value2>(v);
}
};
v
will be just an rvalue-reference.