0
votes

something in is messing out with std::swap and boost::unordered_set ?

I am experiencing some problems while using std::swap and boost::unordered_set. The following code generates a C2039 error on VC2017/VC2019. Comment the line #include and it works finely. Does someone has any clue about this problem ?

#include <vector>
#include <boost/unordered/unordered_set.hpp>
typedef boost::unordered_set<size_t> index_list_type;
int main()
{
    index_list_type toto;
    index_list_type tutu;
    std::swap<index_list_type>(toto, tutu);
    return 0;
}

MSVC\14.20.27508\include\vector(1702): error C2039: '_Alloc' : is not member of 'boost::unordered::unordered_set,std::equal_to,std::allocator>'

2
Why aren't you using std::unordered_set? Boost doesn't have to work with std algorithms. Check here cplusplus.com/reference/algorithm/swap expecially the "all standard containers specialize it in such a way that only a few internal pointers are swapped instead of their entire contents, making them operate in constant time." part. - Barnack
Have you tried removing the 'std::' from 'std::swap' so it relies on name-dependent lookup for overload resolution? - Stephen M. Webb
@Barnack. This issue arose in a library that I wrote some years ago. I did not know that unordered_set was part of the standard library, that's the reason why I did not used it. I had some small sides effects but succeded to use std::unordered_set, hence your answer was the correct one. Thanks a lot. - JohnLeM

2 Answers

0
votes

You should just use std::unordered_set, no need for boost. Boost doesn't have to work with std algorithms. Check here expecially the "all standard containers specialize it in such a way that only a few internal pointers are swapped instead of their entire contents, making them operate in constant time." part.

Sure many things might be cross compatible between boost and std, but if all the tools you need are available in the same namespace, just use that one.

0
votes

Boost is an entire ecosystem in itself, aimed at minimizing the reliance on the C++ standard library (remember that std::swap is available since C++11 only). As such, there is boost::swap(), which has overloads for all Boost data types, including boost::unordered_set:

// swap
template<typename Value, typename Hash, typename Pred, typename Alloc> 
  void swap(unordered_set<Value, Hash, Pred, Alloc>&, 
            unordered_set<Value, Hash, Pred, Alloc>&);

If you use std::swap then you should consider std::unordered_set, and vice versa if you can't or don't want to, then you should stick with Boost all the way. Try to minimize mixing std and boost.


As to the error - this looks like is a bug in the MSVC standard library; the std::swap<vector> implementation is not explicitly restricted to vectors, which is wrong since it fails whenever the type is specified explicitly.

It looks roughly like this:

template<class T>
class _Vb_reference
{
    using _Alvbase = typename T::_Alloc;
};

template<class T>
void swap(_Vb_reference<T> _Left, _Vb_reference<T> _Right)
{
}

That only works when the arguments are deduced, as in

    std::swap(toto, tutu); // _Vb_reference<T> is non-deduced context

But fails when the type is specified explicitly:

    std::swap<index_list_type>(toto, tutu); // instantiation of _Vb_reference<index_list_type> fails = hard error

A better implementation would include some SFINAE to restrict the template to _Vb_reference<T> types.