rc_string_base.h (__rc_string_base<>::_Rep): Avoid the anonymous struct extension, adjust everywhere.

2005-11-18  Paolo Carlini  <pcarlini@suse.de>

	* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Avoid the
	anonymous struct extension, adjust everywhere.

	* include/ext/rc_string_base.h (__rc_string_base<>::_S_empty_rep()):
	Just use a static member.
	(__rc_string_base<>::__rc_string_base(), _S_construct): Adjust.

	* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Use anonymous
	union together with _CharT to fix alignment issues, rebind to _Rep and
	rename _Raw_alloc to _Rep_alloc_type.
	(__rc_string_base<>::_Rep::_S_create, _M_destroy): Adjust consistently.

	* include/ext/vstring_util.h (__is_null_p): Move inside struct
	__vstring_utility as static _S_is_null_pointer.
	* include/ext/sso_string.h
	(__sso_string_base<>::_M_construct(std::forward_iterator_tag): Adjust.
	* include/ext/rc_string_base.h
	(__rc_string_base<>::_S_construct(std::forward_iterator_tag): Likewise.

	Implement Option 3 of DR 431 for ext/vstring - both available bases.
	* include/bits/cpp_type_traits.h (struct __is_empty): Add.
	* include/ext/vstring.h (__versa_string<>::swap): Delegate to
	this->_M_swap.
	* include/ext/vstring.tcc (__versa_string<>::swap): Remove.
	* include/ext/vstring_util.h (struct __vstring_utility<>): Add struct
	_Alloc_hider<>, augmented of allocator swapping facility, specialized
	to nop for empty allocators.
	* include/ext/rc_string_base.h (__rc_string_base<>::_M_swap): Use it.
	(__rc_string_base<>::_M_is_leaked, _M_set_sharable): Change to private.
	* include/ext/sso_string_base.h	(__sso_string_base<>::_M_swap):
	Likewise.
	(__sso_string_base<>::_M_is_leaked, _M_set_sharable): Remove, unused.	

	* include/ext/rc_string_base.h (__rc_string_base<>::_M_data(_CharT*):
	Return void.
	* include/ext/sso_string_base.h (__sso_string_base<>::_M_data(_CharT*):
	Likewise.

From-SVN: r107176
This commit is contained in:
Paolo Carlini 2005-11-18 11:50:22 +00:00 committed by Paolo Carlini
parent e0709888ef
commit 7697e6c66a
7 changed files with 219 additions and 155 deletions

View File

@ -1,3 +1,43 @@
2005-11-18 Paolo Carlini <pcarlini@suse.de>
* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Avoid the
anonymous struct extension, adjust everywhere.
* include/ext/rc_string_base.h (__rc_string_base<>::_S_empty_rep()):
Just use a static member.
(__rc_string_base<>::__rc_string_base(), _S_construct): Adjust.
* include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Use anonymous
union together with _CharT to fix alignment issues, rebind to _Rep and
rename _Raw_alloc to _Rep_alloc_type.
(__rc_string_base<>::_Rep::_S_create, _M_destroy): Adjust consistently.
* include/ext/vstring_util.h (__is_null_p): Move inside struct
__vstring_utility as static _S_is_null_pointer.
* include/ext/sso_string.h
(__sso_string_base<>::_M_construct(std::forward_iterator_tag): Adjust.
* include/ext/rc_string_base.h
(__rc_string_base<>::_S_construct(std::forward_iterator_tag): Likewise.
Implement Option 3 of DR 431 for ext/vstring - both available bases.
* include/bits/cpp_type_traits.h (struct __is_empty): Add.
* include/ext/vstring.h (__versa_string<>::swap): Delegate to
this->_M_swap.
* include/ext/vstring.tcc (__versa_string<>::swap): Remove.
* include/ext/vstring_util.h (struct __vstring_utility<>): Add struct
_Alloc_hider<>, augmented of allocator swapping facility, specialized
to nop for empty allocators.
* include/ext/rc_string_base.h (__rc_string_base<>::_M_swap): Use it.
(__rc_string_base<>::_M_is_leaked, _M_set_sharable): Change to private.
* include/ext/sso_string_base.h (__sso_string_base<>::_M_swap):
Likewise.
(__sso_string_base<>::_M_is_leaked, _M_set_sharable): Remove, unused.
* include/ext/rc_string_base.h (__rc_string_base<>::_M_data(_CharT*):
Return void.
* include/ext/sso_string_base.h (__sso_string_base<>::_M_data(_CharT*):
Likewise.
2005-11-17 Geoffrey Keating <geoffk@apple.com>
* config/os/bsd/darwin/ppc-extra.ver: New.

View File

@ -364,6 +364,26 @@ namespace std
};
};
//
// A stripped-down version of std::tr1::is_empty
//
template<typename _Tp>
struct __is_empty
{
private:
template<typename>
struct __first { };
template<typename _Up>
struct __second
: public _Up { };
public:
enum
{
__value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>)
};
};
} // namespace std
#endif //_CPP_TYPE_TRAITS_H

View File

@ -92,8 +92,8 @@ namespace __gnu_cxx
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type _CharT_alloc_type;
typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
typedef typename _CharT_alloc_type::size_type size_type;
private:
@ -107,16 +107,25 @@ namespace __gnu_cxx
// -1: leaked, one reference, no ref-copies allowed, non-const.
// 0: one reference, non-const.
// n>0: n + 1 references, operations require a lock, const.
// 4. All fields==0 is an empty string, given the extra storage
// 4. All fields == 0 is an empty string, given the extra storage
// beyond-the-end for a null terminator; thus, the shared
// empty string representation needs no constructor.
struct _Rep
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
union
{
struct
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
} _M_info;
// Only for alignment purposes.
_CharT _M_align;
};
typedef typename _Alloc::template rebind<size_type>::other _Raw_alloc;
typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
_CharT*
_M_refdata() throw()
@ -125,15 +134,15 @@ namespace __gnu_cxx
_CharT*
_M_refcopy() throw()
{
__atomic_add(&_M_refcount, 1);
__atomic_add(&_M_info._M_refcount, 1);
return _M_refdata();
} // XXX MT
void
_M_set_length(size_type __n)
{
_M_refcount = 0; // One reference.
_M_length = __n;
_M_info._M_refcount = 0; // One reference.
_M_info._M_length = __n;
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
traits_type::assign(_M_refdata()[__n], _CharT());
@ -150,11 +159,14 @@ namespace __gnu_cxx
_M_clone(const _Alloc&, size_type __res = 0);
};
struct _Rep_empty : _Rep
struct _Rep_empty
: public _Rep
{
_CharT _M_terminal;
_CharT _M_terminal;
};
static _Rep_empty _S_empty_rep;
// The maximum number of individual char_type elements of an
// individual string is determined by _S_max_size. This is the
// value that will be returned by max_size(). (Whereas npos
@ -169,28 +181,12 @@ namespace __gnu_cxx
enum { _S_max_size = (((static_cast<size_type>(-1) - sizeof(_Rep))
/ sizeof(_CharT)) - 1) / 4 };
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(_CharT* __dat, const _Alloc& __a)
: _Alloc(__a), _M_p(__dat) { }
_CharT* _M_p; // The actual data.
};
// Data Member (private):
mutable _Alloc_hider _M_dataplus;
mutable typename _Util_Base::template _Alloc_hider<_Alloc> _M_dataplus;
static _Rep_empty&
_S_empty_rep()
{
static _Rep_empty _Empty_rep;
return _Empty_rep;
}
_CharT*
void
_M_data(_CharT* __p)
{ return (_M_dataplus._M_p = __p); }
{ _M_dataplus._M_p = __p; }
_Rep*
_M_rep() const
@ -206,15 +202,23 @@ namespace __gnu_cxx
void
_M_dispose(const _Alloc& __a)
{
if (__exchange_and_add(&_M_rep()->_M_refcount, -1) <= 0)
if (__exchange_and_add(&_M_rep()->_M_info._M_refcount, -1) <= 0)
_M_rep()->_M_destroy(__a);
} // XXX MT
bool
_M_is_leaked() const
{ return _M_rep()->_M_info._M_refcount < 0; }
void
_M_set_sharable()
{ _M_rep()->_M_info._M_refcount = 0; }
void
_M_leak_hard();
// _S_construct_aux is used to implement the 21.3.1 para 15 which
// requires special behaviour if _InIter is an integral type
// requires special behaviour if _InIterator is an integral type
template<class _InIterator>
static _CharT*
_S_construct_aux(_InIterator __beg, _InIterator __end,
@ -266,31 +270,19 @@ namespace __gnu_cxx
size_type
_M_length() const
{ return _M_rep()->_M_length; }
{ return _M_rep()->_M_info._M_length; }
size_type
_M_capacity() const
{ return _M_rep()->_M_capacity; }
{ return _M_rep()->_M_info._M_capacity; }
bool
_M_is_shared() const
{ return _M_rep()->_M_refcount > 0; }
bool
_M_is_leaked() const
{ return _M_rep()->_M_refcount < 0; }
void
_M_set_sharable()
{ _M_rep()->_M_refcount = 0; }
{ return _M_rep()->_M_info._M_refcount > 0; }
void
_M_set_leaked()
{ _M_rep()->_M_refcount = -1; }
void
_M_set_length(size_type __n)
{ _M_rep()->_M_set_length(__n); }
{ _M_rep()->_M_info._M_refcount = -1; }
void
_M_leak() // for use in begin() & non-const op[]
@ -299,8 +291,12 @@ namespace __gnu_cxx
_M_leak_hard();
}
void
_M_set_length(size_type __n)
{ _M_rep()->_M_set_length(__n); }
__rc_string_base()
: _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { }
: _M_dataplus(_Alloc(), _S_empty_rep._M_refcopy()) { }
__rc_string_base(const _Alloc& __a);
@ -310,7 +306,7 @@ namespace __gnu_cxx
template<typename _InputIterator>
__rc_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a);
const _Alloc& __a);
~__rc_string_base()
{ _M_dispose(_M_get_allocator()); }
@ -320,12 +316,7 @@ namespace __gnu_cxx
{ return _M_dataplus; }
void
_M_swap(__rc_string_base& __rcs)
{
_CharT* __tmp = _M_data();
_M_data(__rcs._M_data());
__rcs._M_data(__tmp);
}
_M_swap(__rc_string_base& __rcs);
void
_M_assign(const __rc_string_base& __rcs);
@ -337,6 +328,10 @@ namespace __gnu_cxx
_M_mutate(size_type __pos, size_type __len1, size_type __len2);
};
template<typename _CharT, typename _Traits, typename _Alloc>
typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
__rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
template<typename _CharT, typename _Traits, typename _Alloc>
typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
@ -388,8 +383,8 @@ namespace __gnu_cxx
// plus sizeof(size_type) - 1 to upper round to a size multiple
// of sizeof(size_type).
// Whew. Seemingly so needy, yet so elemental.
size_type __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
+ sizeof(size_type) - 1);
size_type __size = ((__capacity + 1) * sizeof(_CharT)
+ 2 * sizeof(_Rep) - 1);
const size_type __adj_size = __size + __malloc_header_size;
if (__adj_size > __pagesize && __capacity > __old_capacity)
@ -399,16 +394,14 @@ namespace __gnu_cxx
// Never allocate a string bigger than _S_max_size.
if (__capacity > size_type(_S_max_size))
__capacity = size_type(_S_max_size);
__size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
+ sizeof(size_type) - 1);
__size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
}
// NB: Might throw, but no worries about a leak, mate: _Rep()
// does not throw.
void* __place = _Raw_alloc(__alloc).allocate(__size
/ sizeof(size_type));
_Rep *__p = new (__place) _Rep;
__p->_M_capacity = __capacity;
_Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
_Rep* __p = new (__place) _Rep;
__p->_M_info._M_capacity = __capacity;
return __p;
}
@ -417,10 +410,9 @@ namespace __gnu_cxx
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_M_destroy(const _Alloc& __a) throw ()
{
const size_type __size = ((_M_capacity + 1) * sizeof(_CharT)
+ sizeof(_Rep) + sizeof(size_type) - 1);
_Raw_alloc(__a).deallocate(reinterpret_cast<size_type*>(this),
__size / sizeof(size_type));
const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
+ 2 * sizeof(_Rep) - 1);
_Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
}
template<typename _CharT, typename _Traits, typename _Alloc>
@ -429,41 +421,40 @@ namespace __gnu_cxx
_M_clone(const _Alloc& __alloc, size_type __res)
{
// Requested capacity of the clone.
const size_type __requested_cap = _M_length + __res;
_Rep* __r = _Rep::_S_create(__requested_cap, _M_capacity, __alloc);
const size_type __requested_cap = _M_info._M_length + __res;
_Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
__alloc);
if (_M_length)
_S_copy(__r->_M_refdata(), _M_refdata(), _M_length);
if (_M_info._M_length)
_S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
__r->_M_set_length(_M_length);
__r->_M_set_length(_M_info._M_length);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const _Alloc& __a)
: _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) { }
: _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const __rc_string_base& __rcs)
: _M_dataplus(__rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
__rcs._M_get_allocator()),
__rcs._M_get_allocator()) { }
: _M_dataplus(__rcs._M_get_allocator(),
__rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
__rcs._M_get_allocator())) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
: _M_dataplus(_S_construct(__n, __c, __a), __a)
{ }
: _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InputIterator>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a)
: _M_dataplus(_S_construct(__beg, __end, __a), __a)
{ }
: _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
void
@ -487,7 +478,7 @@ namespace __gnu_cxx
std::input_iterator_tag)
{
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refcopy();
return _S_empty_rep._M_refcopy();
// Avoid reallocation for common case.
_CharT __buf[128];
@ -532,10 +523,10 @@ namespace __gnu_cxx
std::forward_iterator_tag)
{
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refcopy();
return _S_empty_rep._M_refcopy();
// NB: Not required, but considered best practice.
if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
std::__throw_logic_error(__N("__rc_string_base::"
"_S_construct NULL not valid"));
@ -560,7 +551,7 @@ namespace __gnu_cxx
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
if (__n == 0 && __a == _Alloc())
return _S_empty_rep()._M_refcopy();
return _S_empty_rep._M_refcopy();
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
@ -571,6 +562,24 @@ namespace __gnu_cxx
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
_M_swap(__rc_string_base& __rcs)
{
if (_M_is_leaked())
_M_set_sharable();
if (__rcs._M_is_leaked())
__rcs._M_set_sharable();
_CharT* __tmp = _M_data();
_M_data(__rcs._M_data());
__rcs._M_data(__tmp);
// NB: Implement Option 3 of DR 431 (see N1599).
_M_dataplus._M_alloc_swap(__rcs._M_dataplus);
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::

View File

@ -47,8 +47,8 @@ namespace __gnu_cxx
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type _CharT_alloc_type;
typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
typedef typename _CharT_alloc_type::size_type size_type;
private:
@ -66,18 +66,9 @@ namespace __gnu_cxx
enum { _S_max_size = (((static_cast<size_type>(-1)
/ sizeof(_CharT)) - 1) / 4) };
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(const _Alloc& __a, _CharT* __ptr)
: _Alloc(__a), _M_p(__ptr) { }
_CharT* _M_p; // The actual data.
};
// Data Members (private):
_Alloc_hider _M_dataplus;
size_type _M_string_length;
typename _Util_Base::template _Alloc_hider<_Alloc> _M_dataplus;
size_type _M_string_length;
enum { _S_local_capacity = 15 };
@ -87,9 +78,9 @@ namespace __gnu_cxx
size_type _M_allocated_capacity;
};
_CharT*
void
_M_data(_CharT* __p)
{ return (_M_dataplus._M_p = __p); }
{ _M_dataplus._M_p = __p; }
void
_M_length(size_type __length)
@ -118,7 +109,7 @@ namespace __gnu_cxx
_M_destroy(size_type) throw();
// _M_construct_aux is used to implement the 21.3.1 para 15 which
// requires special behaviour if _InIter is an integral type
// requires special behaviour if _InIterator is an integral type
template<class _InIterator>
void
_M_construct_aux(_InIterator __beg, _InIterator __end, __false_type)
@ -181,28 +172,19 @@ namespace __gnu_cxx
_M_is_shared() const
{ return false; }
bool
_M_is_leaked() const
{ return false; }
void
_M_set_sharable() { }
void
_M_set_leaked() { }
void
_M_leak() { }
void
_M_set_length(size_type __n)
{
_M_length(__n);
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
traits_type::assign(_M_data()[__n], _CharT());
}
void
_M_leak() { }
__sso_string_base()
: _M_dataplus(_Alloc(), _M_local_data)
{ _M_set_length(0); }
@ -248,6 +230,9 @@ namespace __gnu_cxx
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_swap(__sso_string_base& __rcs)
{
// NB: Implement Option 3 of DR 431 (see N1599).
_M_dataplus._M_alloc_swap(__rcs._M_dataplus);
if (_M_is_local())
if (__rcs._M_is_local())
{
@ -325,9 +310,6 @@ namespace __gnu_cxx
// The below implements an exponential growth policy, necessary to
// meet amortized linear time requirements of the library: see
// http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
// It's active for allocations requiring an amount of memory above
// system pagesize. This is consistent with the requirements of the
// standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
__capacity = 2 * __old_capacity;
@ -373,7 +355,6 @@ namespace __gnu_cxx
_M_construct(_InIterator __beg, _InIterator __end,
std::input_iterator_tag)
{
// Avoid reallocation for common case.
size_type __len = 0;
size_type __capacity = size_type(_S_local_capacity);
@ -418,7 +399,7 @@ namespace __gnu_cxx
std::forward_iterator_tag)
{
// NB: Not required, but considered best practice.
if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
std::__throw_logic_error(__N("__sso_string_base::"
"_M_construct NULL not valid"));

View File

@ -1214,7 +1214,8 @@ namespace __gnu_cxx
* time.
*/
void
swap(__versa_string& __s);
swap(__versa_string& __s)
{ this->_M_swap(__s); }
// String operations:
/**

View File

@ -218,30 +218,6 @@ namespace __gnu_cxx
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
void
__versa_string<_CharT, _Traits, _Alloc, _Base>::
swap(__versa_string& __s)
{
if (this->_M_is_leaked())
this->_M_set_sharable();
if (__s._M_is_leaked())
__s._M_set_sharable();
if (this->get_allocator() == __s.get_allocator())
this->_M_swap(__s);
// The code below can usually be optimized away.
else
{
const __versa_string __tmp1(_M_ibegin(), _M_iend(),
__s.get_allocator());
const __versa_string __tmp2(__s._M_ibegin(), __s._M_iend(),
this->get_allocator());
*this = __tmp2;
__s = __tmp1;
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
void

View File

@ -1,4 +1,4 @@
// Versatile string utilities -*- C++ -*-
// Versatile string utility -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
@ -47,16 +47,6 @@
namespace __gnu_cxx
{
template<typename _Type>
inline bool
__is_null_p(_Type* __ptr)
{ return __ptr == 0; }
template<typename _Type>
inline bool
__is_null_p(_Type)
{ return false; }
template<typename _CharT, typename _Traits, typename _Alloc>
struct __vstring_utility
{
@ -92,6 +82,53 @@ namespace __gnu_cxx
__rc_string_base> >
__const_rc_iterator;
// NB: When the allocator is empty, deriving from it saves space
// (http://www.cantrip.org/emptyopt.html). We do that anyway for
// consistency.
template<typename _Alloc1, bool = std::__is_empty<_Alloc1>::__value>
struct _Alloc_hider
: public _Alloc1
{
_Alloc_hider(const _Alloc1& __a, _CharT* __ptr)
: _Alloc1(__a), _M_p(__ptr) { }
void
_M_alloc_swap(_Alloc_hider& __ah)
{
// Implement Option 3 of DR 431 (see N1599).
// Precondition: swappable allocators.
_Alloc1& __this = static_cast<_Alloc1&>(*this);
_Alloc1& __that = static_cast<_Alloc1&>(__ah);
if (__this != __that)
swap(__this, __that);
}
_CharT* _M_p; // The actual data.
};
template<typename _Alloc1>
struct _Alloc_hider<_Alloc1, true>
: public _Alloc1
{
_Alloc_hider(const _Alloc1& __a, _CharT* __ptr)
: _Alloc1(__a), _M_p(__ptr) { }
void _M_alloc_swap(_Alloc_hider&) { }
_CharT* _M_p; // The actual data.
};
// For use in _M_construct (_S_construct) forward_iterator_tag.
template<typename _Type>
static bool
_S_is_null_pointer(_Type* __ptr)
{ return __ptr == 0; }
template<typename _Type>
static bool
_S_is_null_pointer(_Type)
{ return false; }
// When __n = 1 way faster than the general multichar
// traits_type::copy/move/assign.
static void