Commit 5c7c5f9a by François Dumont

2014-07-29 François Dumont <fdumont@gcc.gnu.org>

	* testsuite/util/testsuite_allocator.h
	(tracker_allocator_counter::allocate): Remove new invocation, only
	collect information.
	(tracker_allocator_counter::deallocate): Remove delete invocation, only
	collect information.
	(check_inconsistent_alloc_value_type): New.
	(tracker_allocator): Transform as a facade for any allocator type.
	(uneq_allocator): Likewise.
	(propagating_allocator): Likewise.
	* testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an
	explicitly non propagating allocator.
	* testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
	* testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise.
	* testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise.
	* testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
	* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
	Likewise.
	* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
	Likewise.
	* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
	Likewise.
	* testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.

From-SVN: r213224
parent f4081d13
2014-07-29 François Dumont <fdumont@gcc.gnu.org>
* testsuite/util/testsuite_allocator.h
(tracker_allocator_counter::allocate): Remove new invocation, only
collect information.
(tracker_allocator_counter::deallocate): Remove delete invocation, only
collect information.
(check_inconsistent_alloc_value_type): New.
(tracker_allocator): Transform as a facade for any allocator type.
(uneq_allocator): Likewise.
(propagating_allocator): Likewise.
* testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an
explicitly non propagating allocator.
* testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise.
* testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.
2014-07-29 Jonathan Wakely <jwakely@redhat.com> 2014-07-29 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/61946 PR libstdc++/61946
......
...@@ -25,7 +25,7 @@ void test01() ...@@ -25,7 +25,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::forward_list<int, alloc_type> test_type; typedef __gnu_debug::forward_list<int, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -25,7 +25,8 @@ void test01() ...@@ -25,7 +25,8 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
false> alloc_type;
typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type; typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -25,7 +25,8 @@ void test01() ...@@ -25,7 +25,8 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
false> alloc_type;
typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type; typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -25,7 +25,7 @@ void test01() ...@@ -25,7 +25,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type; typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -25,7 +25,7 @@ void test01() ...@@ -25,7 +25,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type; typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -25,7 +25,8 @@ void test01() ...@@ -25,7 +25,8 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
false> alloc_type;
typedef __gnu_debug::unordered_map<int, int, typedef __gnu_debug::unordered_map<int, int,
std::hash<int>, std::equal_to<int>, std::hash<int>, std::equal_to<int>,
alloc_type> test_type; alloc_type> test_type;
......
...@@ -25,7 +25,8 @@ void test01() ...@@ -25,7 +25,8 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type; typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
false> alloc_type;
typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>, typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
std::equal_to<int>, std::equal_to<int>,
alloc_type> test_type; alloc_type> test_type;
......
...@@ -25,7 +25,7 @@ void test01() ...@@ -25,7 +25,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_multiset<int, std::hash<int>, typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
std::equal_to<int>, std::equal_to<int>,
alloc_type> test_type; alloc_type> test_type;
......
...@@ -25,7 +25,7 @@ void test01() ...@@ -25,7 +25,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::unordered_set<int, std::hash<int>, typedef __gnu_debug::unordered_set<int, std::hash<int>,
std::equal_to<int>, std::equal_to<int>,
alloc_type> test_type; alloc_type> test_type;
......
...@@ -27,7 +27,7 @@ void test01() ...@@ -27,7 +27,7 @@ void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
typedef __gnu_test::uneq_allocator<int> alloc_type; typedef __gnu_test::propagating_allocator<int, false> alloc_type;
typedef __gnu_debug::vector<int, alloc_type> test_type; typedef __gnu_debug::vector<int, alloc_type> test_type;
test_type v1(alloc_type(1)); test_type v1(alloc_type(1));
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <tr1/unordered_map> #include <tr1/unordered_map>
#include <bits/move.h> #include <bits/move.h>
#include <ext/pointer.h> #include <ext/pointer.h>
#include <ext/alloc_traits.h>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
namespace __gnu_test namespace __gnu_test
...@@ -38,26 +39,19 @@ namespace __gnu_test ...@@ -38,26 +39,19 @@ namespace __gnu_test
public: public:
typedef std::size_t size_type; typedef std::size_t size_type;
static void* static void
allocate(size_type blocksize) allocate(size_type blocksize)
{ { allocationCount_ += blocksize; }
void* p = ::operator new(blocksize);
allocationCount_ += blocksize;
return p;
}
static void static void
construct() { constructCount_++; } construct() { ++constructCount_; }
static void static void
destroy() { destructCount_++; } destroy() { ++destructCount_; }
static void static void
deallocate(void* p, size_type blocksize) deallocate(size_type blocksize)
{ { deallocationCount_ += blocksize; }
::operator delete(p);
deallocationCount_ += blocksize;
}
static size_type static size_type
get_allocation_count() { return allocationCount_; } get_allocation_count() { return allocationCount_; }
...@@ -87,103 +81,142 @@ namespace __gnu_test ...@@ -87,103 +81,142 @@ namespace __gnu_test
static int destructCount_; static int destructCount_;
}; };
// A simple basic allocator that just forwards to the // Helper to detect inconsistency between type used to instantiate an
// tracker_allocator_counter to fulfill memory requests. This class // allocator and the underlying allocator value_type.
// is templated on the target object type, but tracker isn't. template<typename T, typename Alloc,
template<class T> typename = typename Alloc::value_type>
class tracker_allocator struct check_consistent_alloc_value_type;
{
private: template<typename T, typename Alloc>
typedef tracker_allocator_counter counter_type; struct check_consistent_alloc_value_type<T, Alloc, T>
{ typedef T value_type; };
public:
typedef T value_type; // An allocator facade that intercepts allocate/deallocate/construct/destroy
typedef T* pointer; // calls and track them through the tracker_allocator_counter class. This
typedef const T* const_pointer; // class is templated on the target object type, but tracker isn't.
typedef T& reference; template<typename T, typename Alloc = std::allocator<T> >
typedef const T& const_reference; class tracker_allocator : public Alloc
typedef std::size_t size_type; {
typedef std::ptrdiff_t difference_type; private:
typedef tracker_allocator_counter counter_type;
template<class U> struct rebind { typedef tracker_allocator<U> other; };
pointer
address(reference value) const _GLIBCXX_NOEXCEPT
{ return std::__addressof(value); }
const_pointer typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
address(const_reference value) const _GLIBCXX_NOEXCEPT
{ return std::__addressof(value); }
tracker_allocator() _GLIBCXX_USE_NOEXCEPT public:
{ } typedef typename
check_consistent_alloc_value_type<T, Alloc>::value_type value_type;
typedef typename AllocTraits::pointer pointer;
typedef typename AllocTraits::size_type size_type;
tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT template<class U>
{ } struct rebind
{
typedef tracker_allocator<U,
typename AllocTraits::template rebind<U>::other> other;
};
#if __cplusplus >= 201103L
tracker_allocator() = default;
tracker_allocator(const tracker_allocator&) = default;
tracker_allocator(tracker_allocator&&) = default;
// Perfect forwarding constructor.
template<typename... _Args>
tracker_allocator(_Args&&... __args)
: Alloc(std::forward<_Args>(__args)...)
{ }
#else
tracker_allocator()
{ }
template<class U> tracker_allocator(const tracker_allocator&)
tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT
{ } { }
~tracker_allocator() _GLIBCXX_USE_NOEXCEPT ~tracker_allocator()
{ } { }
#endif
size_type template<class U>
max_size() const _GLIBCXX_USE_NOEXCEPT tracker_allocator(const tracker_allocator<U,
{ return size_type(-1) / sizeof(T); } typename AllocTraits::template rebind<U>::other>& alloc)
_GLIBCXX_USE_NOEXCEPT
: Alloc(alloc)
{ }
pointer pointer
allocate(size_type n, const void* = 0) allocate(size_type n, const void* = 0)
{ return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); } {
pointer p = AllocTraits::allocate(*this, n);
counter_type::allocate(n * sizeof(T));
return p;
}
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename U, typename... Args> template<typename U, typename... Args>
void
construct(U* p, Args&&... args)
{
AllocTraits::construct(*this, p, std::forward<Args>(args)...);
counter_type::construct();
}
template<typename U>
void
destroy(U* p)
{
AllocTraits::destroy(*this, p);
counter_type::destroy();
}
#else
void void
construct(U* p, Args&&... args) construct(pointer p, const T& value)
{ {
::new((void *)p) U(std::forward<Args>(args)...); AllocTraits::construct(*this, p, value);
counter_type::construct(); counter_type::construct();
} }
template<typename U>
void void
destroy(U* p) destroy(pointer p)
{ {
p->~U(); AllocTraits::destroy(*this, p);
counter_type::destroy(); counter_type::destroy();
} }
#else
void
construct(pointer p, const T& value)
{
::new ((void *)p) T(value);
counter_type::construct();
}
void
destroy(pointer p)
{
p->~T();
counter_type::destroy();
}
#endif #endif
void void
deallocate(pointer p, size_type num) deallocate(pointer p, size_type num)
{ counter_type::deallocate(p, num * sizeof(T)); } {
}; counter_type::deallocate(num * sizeof(T));
AllocTraits::deallocate(*this, p, num);
}
// Implement swap for underlying allocators that might need it.
friend inline void
swap(tracker_allocator& a, tracker_allocator& b)
{
using std::swap;
template<class T1, class T2> Alloc& aa = a;
Alloc& ab = b;
swap(aa, ab);
}
};
template<class T1, class Alloc1, class T2, class Alloc2>
bool bool
operator==(const tracker_allocator<T1>&, operator==(const tracker_allocator<T1, Alloc1>& lhs,
const tracker_allocator<T2>&) throw() const tracker_allocator<T2, Alloc2>& rhs) throw()
{ return true; } {
const Alloc1& alloc1 = lhs;
const Alloc2& alloc2 = rhs;
return lhs == rhs;
}
template<class T1, class T2> template<class T1, class Alloc1, class T2, class Alloc2>
bool bool
operator!=(const tracker_allocator<T1>&, operator!=(const tracker_allocator<T1, Alloc1>& lhs,
const tracker_allocator<T2>&) throw() const tracker_allocator<T2, Alloc2>& rhs) throw()
{ return false; } { return !(lhs == rhs); }
bool bool
check_construct_destroy(const char* tag, int expected_c, int expected_d); check_construct_destroy(const char* tag, int expected_c, int expected_d);
...@@ -193,7 +226,7 @@ namespace __gnu_test ...@@ -193,7 +226,7 @@ namespace __gnu_test
check_deallocate_null() check_deallocate_null()
{ {
// Let's not core here... // Let's not core here...
Alloc a; Alloc a;
a.deallocate(0, 1); a.deallocate(0, 1);
a.deallocate(0, 10); a.deallocate(0, 10);
return true; return true;
...@@ -219,7 +252,6 @@ namespace __gnu_test ...@@ -219,7 +252,6 @@ namespace __gnu_test
throw; throw;
} }
// A simple allocator which can be constructed endowed of a given // A simple allocator which can be constructed endowed of a given
// "personality" (an integer), queried in operator== to simulate the // "personality" (an integer), queried in operator== to simulate the
// behavior of realworld "unequal" allocators (i.e., not exploiting // behavior of realworld "unequal" allocators (i.e., not exploiting
...@@ -227,7 +259,7 @@ namespace __gnu_test ...@@ -227,7 +259,7 @@ namespace __gnu_test
// filled at allocation time with (pointer, personality) pairs, is // filled at allocation time with (pointer, personality) pairs, is
// then consulted to enforce the requirements in Table 32 about // then consulted to enforce the requirements in Table 32 about
// deallocation vs allocator equality. Note that this allocator is // deallocation vs allocator equality. Note that this allocator is
// swappable, not assignable, consistently with Option 3 of DR 431 // swappable, not copy assignable, consistently with Option 3 of DR 431
// (see N1599). // (see N1599).
struct uneq_allocator_base struct uneq_allocator_base
{ {
...@@ -244,35 +276,49 @@ namespace __gnu_test ...@@ -244,35 +276,49 @@ namespace __gnu_test
} }
}; };
template<typename Tp> template<typename Tp, typename Alloc = std::allocator<Tp> >
class uneq_allocator class uneq_allocator
: private uneq_allocator_base : private uneq_allocator_base,
public Alloc
{ {
typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
Alloc& base() { return *this; }
const Alloc& base() const { return *this; }
void swap_base(Alloc& b) { swap(b, this->base()); }
public: public:
typedef std::size_t size_type; typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type
typedef std::ptrdiff_t difference_type; value_type;
typedef Tp* pointer; typedef typename AllocTraits::size_type size_type;
typedef const Tp* const_pointer; typedef typename AllocTraits::pointer pointer;
typedef Tp& reference;
typedef const Tp& const_reference;
typedef Tp value_type;
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
typedef std::true_type propagate_on_container_swap; typedef std::true_type propagate_on_container_swap;
#endif #endif
template<typename Tp1> template<typename Tp1>
struct rebind struct rebind
{ typedef uneq_allocator<Tp1> other; }; {
typedef uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other> other;
};
uneq_allocator() _GLIBCXX_USE_NOEXCEPT uneq_allocator() _GLIBCXX_USE_NOEXCEPT
: personality(0) { } : personality(0) { }
uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT
: personality(person) { } : personality(person) { }
#if __cplusplus >= 201103L
uneq_allocator(const uneq_allocator&) = default;
uneq_allocator(uneq_allocator&&) = default;
#endif
template<typename Tp1> template<typename Tp1>
uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT uneq_allocator(const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
_GLIBCXX_USE_NOEXCEPT
: personality(b.get_personality()) { } : personality(b.get_personality()) { }
~uneq_allocator() _GLIBCXX_USE_NOEXCEPT ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
...@@ -281,20 +327,10 @@ namespace __gnu_test ...@@ -281,20 +327,10 @@ namespace __gnu_test
int get_personality() const { return personality; } int get_personality() const { return personality; }
pointer pointer
address(reference x) const _GLIBCXX_NOEXCEPT allocate(size_type n, const void* hint = 0)
{ return std::__addressof(x); }
const_pointer
address(const_reference x) const _GLIBCXX_NOEXCEPT
{ return std::__addressof(x); }
pointer
allocate(size_type n, const void* = 0)
{ {
if (__builtin_expect(n > this->max_size(), false)) pointer p = AllocTraits::allocate(*this, n);
std::__throw_bad_alloc();
pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
try try
{ {
get_map().insert(map_type::value_type(reinterpret_cast<void*>(p), get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
...@@ -302,14 +338,15 @@ namespace __gnu_test ...@@ -302,14 +338,15 @@ namespace __gnu_test
} }
catch(...) catch(...)
{ {
::operator delete(p); AllocTraits::deallocate(*this, p, n);
__throw_exception_again; __throw_exception_again;
} }
return p; return p;
} }
void void
deallocate(pointer p, size_type) deallocate(pointer p, size_type n)
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
...@@ -323,34 +360,18 @@ namespace __gnu_test ...@@ -323,34 +360,18 @@ namespace __gnu_test
VERIFY( it->second == personality ); VERIFY( it->second == personality );
get_map().erase(it); get_map().erase(it);
::operator delete(p); AllocTraits::deallocate(*this, p, n);
} }
size_type
max_size() const _GLIBCXX_USE_NOEXCEPT
{ return size_type(-1) / sizeof(Tp); }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename U, typename... Args>
void
construct(U* p, Args&&... args)
{ ::new((void *)p) U(std::forward<Args>(args)...); }
template<typename U>
void
destroy(U* p) { p->~U(); }
// Not copy assignable... // Not copy assignable...
uneq_allocator& uneq_allocator&
operator=(const uneq_allocator&) = delete; operator=(const uneq_allocator&) = delete;
#else
void
construct(pointer p, const Tp& val)
{ ::new((void *)p) Tp(val); }
void
destroy(pointer p) { p->~Tp(); }
// ... but still moveable if base allocator is.
uneq_allocator&
operator=(uneq_allocator&&) = default;
#else
private: private:
// Not assignable... // Not assignable...
uneq_allocator& uneq_allocator&
...@@ -358,31 +379,39 @@ namespace __gnu_test ...@@ -358,31 +379,39 @@ namespace __gnu_test
#endif #endif
private: private:
// ... yet swappable! // ... yet swappable!
friend inline void friend inline void
swap(uneq_allocator& a, uneq_allocator& b) swap(uneq_allocator& a, uneq_allocator& b)
{ std::swap(a.personality, b.personality); } {
std::swap(a.personality, b.personality);
a.swap_base(b);
}
template<typename Tp1> template<typename Tp1>
friend inline bool friend inline bool
operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b) operator==(const uneq_allocator& a,
{ return a.personality == b.personality; } const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
{ return a.personality == b.personality; }
template<typename Tp1> template<typename Tp1>
friend inline bool friend inline bool
operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b) operator!=(const uneq_allocator& a,
{ return !(a == b); } const uneq_allocator<Tp1,
typename AllocTraits::template rebind<Tp1>::other>& b)
{ return !(a == b); }
int personality; int personality;
}; };
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
// An uneq_allocator which can be used to test allocator propagation. // An uneq_allocator which can be used to test allocator propagation.
template<typename Tp, bool Propagate> template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>>
class propagating_allocator : public uneq_allocator<Tp> class propagating_allocator : public uneq_allocator<Tp, Alloc>
{ {
typedef uneq_allocator<Tp> base_alloc; typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
typedef uneq_allocator<Tp, Alloc> base_alloc;
base_alloc& base() { return *this; } base_alloc& base() { return *this; }
const base_alloc& base() const { return *this; } const base_alloc& base() const { return *this; }
void swap_base(base_alloc& b) { swap(b, this->base()); } void swap_base(base_alloc& b) { swap(b, this->base()); }
...@@ -393,15 +422,20 @@ namespace __gnu_test ...@@ -393,15 +422,20 @@ namespace __gnu_test
// default allocator_traits::rebind_alloc would select // default allocator_traits::rebind_alloc would select
// uneq_allocator::rebind so we must define rebind here // uneq_allocator::rebind so we must define rebind here
template<typename Up> template<typename Up>
struct rebind { typedef propagating_allocator<Up, Propagate> other; }; struct rebind
{
typedef propagating_allocator<Up, Propagate,
typename AllocTraits::template rebind<Up>::other> other;
};
propagating_allocator(int i) noexcept propagating_allocator(int i) noexcept
: base_alloc(i) : base_alloc(i)
{ } { }
template<typename Up> template<typename Up>
propagating_allocator(const propagating_allocator<Up, Propagate>& a) propagating_allocator(const propagating_allocator<Up, Propagate,
noexcept typename AllocTraits::template rebind<Up>::other>& a)
noexcept
: base_alloc(a) : base_alloc(a)
{ } { }
...@@ -418,8 +452,8 @@ namespace __gnu_test ...@@ -418,8 +452,8 @@ namespace __gnu_test
} }
template<bool P2> template<bool P2>
propagating_allocator& propagating_allocator&
operator=(const propagating_allocator<Tp, P2>& a) noexcept operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
{ {
static_assert(P2, "assigning propagating_allocator<T, true>"); static_assert(P2, "assigning propagating_allocator<T, true>");
propagating_allocator(a).swap_base(*this); propagating_allocator(a).swap_base(*this);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment