У меня есть вопрос об использовании std :: weak_ptr в качестве ключа для std :: map.
#include <map>
#include <memory>
int main()
{
std::map< std::weak_ptr<int>, bool > myMap;
std::shared_ptr<int> sharedptr(new int(5));
std::weak_ptr<int> weakptr = sharedptr;
myMap[weakptr] = true;
return 0;
}
Вышеприведенная программа не собирается, и при попытке компиляции выдается много сообщений об ошибках, таких как:
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xfunctional(125): error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::tr1::weak_ptr<_Ty>'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xtree(1885) : see declaration of 'std::operator <'
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xfunctional(124) : while compiling class template member function 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const'
1> with
1> [
1> _Ty=std::tr1::weak_ptr<int>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\map(71) : see reference to class template instantiation 'std::less<_Ty>' being compiled
1> with
1> [
1> _Ty=std::tr1::weak_ptr<int>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xtree(451) : see reference to class template instantiation 'std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,_Mfl>' being compiled
1> with
1> [
1> _Kty=std::tr1::weak_ptr<int>,
1> _Ty=bool,
1> _Pr=std::less<std::tr1::weak_ptr<int>>,
1> _Alloc=std::allocator<std::pair<const std::tr1::weak_ptr<int>,bool>>,
1> _Mfl=false
1> ]
Проблема возникает из-за следующей строки:
myMap[weakptr] = true;
Сообщения об ошибках, похоже, связаны с оператором<, Нужно ли определять оператора< для слабых_птрс? Какие именно операторы необходимо определить, чтобы использовать тип данных в качестве ключа для std :: map?
(Должен заметить, что я уже определил operator == в пространстве имен std. Также я планирую использовать weak_ptr для пользовательского типа класса, а не int.)
C ++ 11 предоставляет соответствующие механизмы для сравнения std::weak_ptr
а именно: std::owner_less
,
Это должно быть по умолчанию для карт и наборов. Если используемый вами компилятор C ++ испытывает трудности, попробуйте использовать std::owner_less
если это доступно. Если он недоступен, вам необходимо предоставить механизм, аналогичный std::owner_less
так что вы можете соответствующим образом сравнить std::weak_ptr
объекты.
Третий аргумент шаблона для std :: map<> по умолчанию используется std :: less, который обычно просто вызывает оператор<() для ключа. Таким образом, вы можете любой определенный оператор<() для std :: weak_ptr<> (что, вероятно, является плохой идеей) или просто создайте функтор и укажите его в качестве третьего аргумента шаблона для std :: map<>.
Несмотря на это, я не уверен, может ли это действительно работать, потому что std :: map<> ожидает, что ключи будут неизменными, тогда как std :: weak_ptr<> может измениться в любое время (значение указателя может стать нулевым).
struct WeakPtrLess
{
template <typename T>
bool operator() (const std::weak_ptr<T>& l, const std::weak_ptr<T>& r) const
{
std::shared_ptr<T> sl = l.lock();
std::shared_ptr<T> sr = r.lock();
return sl.get() < sr.get();
}
};
Используйте это на свой страх и риск. (Или каково бы ни было выражение)