1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
#include <vector>
#include <type_traits>
#include <iostream>
template< typename T, typename A >
void safe_swap( std::vector<T,A>& a, std::vector<T,A>& b )
{
// If std::allocator_traits<allocator_type>::propagate_on_container_swap::value is true,
// then the allocators are exchanged using an unqualified call to non-member swap.
// Otherwise, they are not swapped
// (and if get_allocator() != other.get_allocator(), the behavior is undefined).
// http://en.cppreference.com/w/cpp/container/vector/swap
if( ( std::allocator_traits<A>::propagate_on_container_swap::value ) ||
( a.get_allocator() == b.get_allocator() ) )
{
// ok, swap the allocators if required, no copy or move of elements in the vectors
a.swap(b) ;
std::cout << "swapped using std::vector<>::swap\n" ;
}
else
{
// avoid undefined behaviour: implement swap by moving the elements
const auto temp( std::move(a) ) ; // EDIT: ???
// Move assignment operator. Replaces the contents with those of other using move semantics
// (i.e. the data in other is moved from other into this container).
// If std::allocator_traits<allocator_type>::propagate_on_container_move_assignment()
// is false (it is false here, or the else clause would not have been entered into)
// and the source and the target allocators do not compare equal (they do not compare equal here),
// the target cannot take ownership of the source memory and must move-assign each element individually
// http://en.cppreference.com/w/cpp/container/vector/operator%3D
a = std::move(b) ;
b = std::move(temp) ;
std::cout << "swapped by moving the elements;\n\t\t"
"(allocators aren't equal and they can't be swapped)\n" ;
}
}
struct my_allocator : public std::allocator<int>
{
using std::allocator<int>::allocator ;
static constexpr bool is_always_equal = false ;
static constexpr bool propagate_on_container_move_assignment = false ;
friend bool operator== ( const my_allocator&, const my_allocator& ) { return false ; }
friend bool operator!= ( const my_allocator&, const my_allocator& ) { return true ; }
};
int main()
{
{
std::cout << "std::vector with the default allocator: " ;
std::vector<int> a(100), b(200) ;
safe_swap(a,b) ;
}
{
std::cout << "\nstd::vector with the my_allocator: " ;
std::vector< int, my_allocator > a(100), b(200) ;
safe_swap(a,b) ;
}
}
|