From 5e03867448c1bc2b84ac1497d0252c21d05926e4 Mon Sep 17 00:00:00 2001 From: Piotr Rak Date: Tue, 20 Jul 2010 11:16:02 +0200 Subject: [PATCH] Add std::allocator_traits, missing members test. --- libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/bits/alloc_traits.h | 428 ++++++++++++++++++++ libstdc++-v3/include/std/memory | 1 + .../allocator_traits/requirements/typedefs.cc | 179 ++++++++ 5 files changed, 610 insertions(+), 0 deletions(-) create mode 100644 libstdc++-v3/include/bits/alloc_traits.h create mode 100644 libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs.cc diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 96e28fb..26730b9 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -78,6 +78,7 @@ bits_builddir = ./bits bits_headers = \ ${bits_srcdir}/algorithmfwd.h \ ${bits_srcdir}/allocator.h \ + ${bits_srcdir}/alloc_traits.h \ ${bits_srcdir}/atomic_base.h \ ${bits_srcdir}/atomicfwd_c.h \ ${bits_srcdir}/atomicfwd_cxx.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index a800c10..582d116 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -320,6 +320,7 @@ bits_builddir = ./bits bits_headers = \ ${bits_srcdir}/algorithmfwd.h \ ${bits_srcdir}/allocator.h \ + ${bits_srcdir}/alloc_traits.h \ ${bits_srcdir}/atomic_base.h \ ${bits_srcdir}/atomicfwd_c.h \ ${bits_srcdir}/atomicfwd_cxx.h \ diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h new file mode 100644 index 0000000..d2ad6d7 --- /dev/null +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -0,0 +1,428 @@ +// allocator_traits implementation -*- C++ -*- + +// Copyright (C) 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file allocator_traits.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _ALLOC_TRAITS_H +#define _ALLOC_TRAITS_H 1 + +#include +#include +#include +#include +#include + +_GLIBCXX_BEGIN_NAMESPACE(std) + +#define _DEFINE_HAS_MEMTY_AUX(_Name, _MemType) \ + template \ + struct __has_ ## _Name \ + : std::__sfinae_types \ + { \ + template \ + static __one __test(typename _Tp1::_MemType*); \ + \ + template \ + static __two __test(...); \ + \ + static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1; \ + }; + +#define _DEFINE_HAS_MEMTY(_MemType) \ + _DEFINE_HAS_MEMTY_AUX(_MemType, _MemType) + +#define _DEFINE_HAS_POC(_Property) \ + _DEFINE_HAS_MEMTY_AUX(poc_ ## _Property, \ + propagate_on_container_ ## _Property) + +#define _DEFINE_ALLOC_MEMTY(_MemType, _DefType) \ + template ::__value> \ + struct __alloc_ ## _MemType \ + { typedef typename _Tp::_MemType __type; }; \ + \ + template \ + struct __alloc_ ## _MemType<_Tp, false> \ + { typedef typename _DefType __type; }; + +#define _DEFINE_CONCAT(...) __VA_ARGS__ + +#define _DEFINE_ALLOC_MEMTY_PTR(_MemType, _ToType) \ + _DEFINE_ALLOC_MEMTY(_MemType, \ + _DEFINE_CONCAT(__rebind_ptr_to<_Tp, \ + _ToType>::__type)) + +#define _DEFINE_ALLOC_MEMTY_POC(_Mem) \ + template ::__value> \ + struct __alloc_poc_ ## _Mem \ + { typedef typename _Tp::propagate_on_container_ ## _Mem __type; }; \ + \ + template \ + struct __alloc_poc_ ## _Mem<_Tp, false> \ + { typedef typename std::false_type __type; }; + + // __has_pointer + _DEFINE_HAS_MEMTY(pointer) + + // __has_const_pointer + _DEFINE_HAS_MEMTY(const_pointer) + + // __has_void_pointer + _DEFINE_HAS_MEMTY(void_pointer) + + // __has_const_void_pointer + _DEFINE_HAS_MEMTY(const_void_pointer) + + // __has_size_type + _DEFINE_HAS_MEMTY(size_type) + + // __has_poc_copy_assignment + _DEFINE_HAS_POC(copy_assignment) + + // __has_poc_move_assignment + _DEFINE_HAS_POC(move_assignment) + + // __has_poc_swap + _DEFINE_HAS_POC(swap) + + template + struct __has_rebind_other + : __sfinae_types + { + template + static __one __test(typename _Tp1::template rebind<_Up>::other*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1; + }; + + template + struct __has_construct + : __sfinae_types + { + template + static decltype(std::declval<_Up>().construct(std::declval<_Up1*>(), + std::declval<_Args1>()...), __one()) __test(void*); + + template + static __two __test(...); + + static const bool __value = + sizeof(__test<_Tp, _Tp1, _Args...>(nullptr)) == 1; + typedef typename integral_constant::type __type; + }; + +// XXX: Workaround for PR c++/44967 below: +// (specializations for fixed number of template parameters to construct<>() ) + + template + struct __has_construct<_Tp, _Tp1> + : __sfinae_types + { + template + static decltype( std::declval<_Up>().construct( + std::declval<_Up1*>()), __one() ) __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp, _Tp1>(nullptr)) == 1; + typedef typename integral_constant::type __type; + + }; + + template + struct __has_construct<_Tp, _Tp1, _Tp2> + : __sfinae_types + { + template + static decltype(std::declval<_Up>().construct(std::declval<_Up1*>()), + std::declval<_Up2>(), __one()) __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp, _Tp1, _Tp2>(nullptr)) == 1; + typedef typename integral_constant::type __type; + + }; + + template + struct __has_destroy + : __sfinae_types + { + template + static decltype(std::declval<_Up>().destroy( + std::declval<_Up1*>()), __one()) __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp, _Tp1>(nullptr)) == 1; + typedef typename integral_constant::type __type; + }; + + template + struct __has_max_size + : __sfinae_types + { + template + static decltype(std::declval<_Tp1>().max_size(), __one()) __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1; + typedef typename integral_constant::type __type; + }; + + template + struct __has_select_on_container_copy_construction + : __sfinae_types + { + template + static decltype( + std::declval<_Up>().select_on_container_copy_construction(), __one() ) + __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1; + typedef typename std::integral_constant::type __type; + }; + + // __alloc_pointer + _DEFINE_ALLOC_MEMTY(pointer, _Tp::value_type*); + + template + struct __rebind_ptr_to + { + private: + typedef typename __alloc_pointer<_Tp>::__type _PtrType; + + public: +#if 0 + typedef typename pointer_traits<_PtrType> + ::template rebind<_Up> __type; +#else + typedef typename pointer_traits<_PtrType> + ::template rebind<_Up>::other __type; +#endif + }; + + // __alloc_const_pointer + _DEFINE_ALLOC_MEMTY_PTR(const_pointer, const typename _Tp::value_type) + + // __alloc_void_pointer + _DEFINE_ALLOC_MEMTY_PTR(void_pointer, void) + + // __alloc_const_void_pointer + _DEFINE_ALLOC_MEMTY_PTR(const_void_pointer, const void) + + // __alloc_difference_type + _DEFINE_ALLOC_MEMTY(difference_type, std::ptrdiff_t) + + // __alloc_size_type + _DEFINE_ALLOC_MEMTY(size_type, std::size_t) + + // __alloc_poc_copy_assignment + _DEFINE_ALLOC_MEMTY_POC(copy_assignment) + + // __alloc_poc_move_assignment + _DEFINE_ALLOC_MEMTY_POC(move_assignment) + + // __alloc_poc_swap + _DEFINE_ALLOC_MEMTY_POC(swap) + + template + struct __alloc_rebind_alloc + : __ptr_rebind<_Tp, _Up, __has_rebind_other<_Tp, _Up>::__value> + { }; + + template + struct __has_allocate_with_hint + : __sfinae_types + { + typedef typename __alloc_size_type<_Tp>::__type _SizeType; + typedef typename __alloc_const_void_pointer<_Tp>::__type _CVoidPtr; + + template + static decltype( std::declval<_Tp1>().allocate( + std::declval<_SizeType>(), std::declval<_CVoidPtr>()), __one() ) + __test(void*); + + template + static __two __test(...); + + static const bool __value = sizeof(__test<_Tp>(nullptr)) == 1; + typedef typename integral_constant::type __type; + }; + + /** + * @addtogroup allocators + * @{ + */ + + template + struct allocator_traits + { + + // Typedefs. + typedef _Tp allocator_type; + typedef typename _Tp::value_type value_type; + + typedef typename __alloc_pointer<_Tp>::__type pointer; + typedef typename __alloc_const_pointer<_Tp>::__type const_pointer; + typedef typename __alloc_void_pointer<_Tp>::__type void_pointer; + typedef typename + __alloc_const_void_pointer<_Tp>::__type const_void_pointer; + + typedef typename __alloc_difference_type<_Tp>::__type difference_type; + typedef typename __alloc_size_type<_Tp>::__type size_type; + + typedef typename __alloc_poc_copy_assignment<_Tp>::__type + propagate_on_container_copy_assignment; + typedef typename __alloc_poc_move_assignment<_Tp>::__type + propagate_on_container_move_assignment; + typedef typename __alloc_poc_swap<_Tp>::__type + propagate_on_container_swap; + + template +#if 0 + using rebind_alloc = __alloc_rebind_alloc<_Tp, _Up>::__type; +#else + struct rebind_alloc + { typedef typename __alloc_rebind_alloc<_Tp, _Up>::__type other; }; +#endif + + template +#if 0 + using rebind_traits = allocator_traits>; +#else + struct rebind_traits + { typedef allocator_traits::other> other; }; +#endif + + // Members. + static pointer allocate(_Tp& __a, size_type __n) + { return __a.allocate(__n); } + + static pointer allocate(_Tp& __a, size_type __n, const_void_pointer __h) + { + return _S_allocate(__a, __n, __h, + typename __has_allocate_with_hint<_Tp>::__type()); + } + + static void deallocate(_Tp& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + template + static void construct(_Tp& __a, _Up* __p, _Args&&... __args) + { + _S_construct(typename __has_construct<_Tp, _Up, _Args...>::__type(), + __a, __p, std::forward<_Args>(__args)...); + } + + template + static void destroy(_Tp& __a, _Up* __p) + { _S_destroy(__a, __p, typename __has_destroy<_Tp, _Up>::__type()); } + + // XXX: in FCD static size_type max_size(/*missing const*/_Tp&) + // however it would break scoped_allocator_adaptor::max_size() const + static size_type max_size(const _Tp& __a) + { return _S_max_size(__a, typename __has_max_size::__type()); } + + static _Tp select_on_container_copy_construction(const _Tp& __a) + { + typedef __has_select_on_container_copy_construction _Select; + return _S_select_on_copy_construction(__a, typename _Select::__type()); + } + + private: + static pointer _S_allocate(_Tp& __a, + size_type __n, + const_void_pointer __h, + true_type) + { return __a.allocate(__n, __h); } + + static pointer _S_allocate(_Tp& __a, + size_type __n, + const_void_pointer, + false_type) + { return __a.allocate(__n); } + + template + static void _S_construct(true_type, + _Tp& __a, + _Up* __p, + _Args&&... __args) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + template + static void _S_construct(false_type, + _Tp&, + _Up* __p, + _Args&&... __args) + { ::new (static_cast(__p)) _Up(std::forward<_Args>(__args)...); } + + template + static void _S_destroy(_Tp& __a, _Up* __p, true_type) + { __a.destroy(__p); } + + template + static void _S_destroy(_Tp&, _Up* __p, false_type) + { __p->~_Up(); } + + static size_type _S_max_size(const _Tp& __a, true_type) + { return __a.max_size(); } + + static size_type _S_max_size(const _Tp&, false_type) + { return numeric_limits::max(); } + + static _Tp&& _S_select_on_copy_construction(const _Tp& __a, true_type) + { return std::forward<_Tp>(__a.select_on_container_copy_construction()); } + + static _Tp _S_select_on_copy_construction(const _Tp& __a, false_type) + { return __a; } + }; + + /// @} group allocators + +#undef _DEFINE_HAS_MEMTY +#undef _DEFINE_HAS_MEMTY_AUX +#undef _DEFINE_HAS_POC +#undef _DEFINE_CONCAT +#undef _DEFINE_ALLOC_MEMTY +#undef _DEFINE_ALLOC_MEMTY_PTR +#undef _DEFINE_ALLOC_MEMTY_POC + +_GLIBCXX_END_NAMESPACE + +#endif /* _ALLOC_TRAITS_H */ + diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index f070f34..5b51ef0 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -78,6 +78,7 @@ # include # include # include +# include # include // std::less # include # include diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs.cc new file mode 100644 index 0000000..ed095c1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs.cc @@ -0,0 +1,179 @@ +// { dg-options "-std=gnu++0x" } +// 2010-07-19 Piotr Rak +// +// Copyright (C) 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include + +struct test_type01 { }; +struct test_type02 { }; +struct test_type03 { }; +struct test_type04 { }; +struct test_type05 { }; +struct test_type06 { }; +struct test_type07 { }; +struct test_type08 { }; +struct test_type09 { }; +struct test_type10 { }; +struct test_type11 { }; + +// Minimal. +template +struct A0 +{ + typedef Tp_ value_type; + Tp_* allocate(std::size_t); + + void deallocate(Tp_*, std::size_t); +}; + +// Minimal + a.allocate(n, hint). +template +struct A1 +{ + typedef Tp_ value_type; + + Tp_* allocate(std::size_t); + Tp_* allocate(std::size_t, const void*); + + void deallocate(Tp_*, std::size_t); +}; + +// All members. +struct A2 +{ + typedef test_type01 value_type; + typedef test_type02 pointer; + typedef test_type03 const_pointer; + typedef test_type04 void_pointer; + typedef test_type05 const_void_pointer; + + typedef test_type06 difference_type; + typedef test_type07 size_type; + + typedef test_type08 propagate_on_container_copy_assignment; + typedef test_type09 propagate_on_container_move_assignment; + typedef test_type10 propagate_on_container_swap; + + template + struct rebind + { typedef test_type11 other; }; + + pointer allocate(size_type); + pointer allocate(size_type, const_void_pointer); + + void deallocate(pointer, size_type); + + template + void construct(Tp_*, Args_&&...); + + template + void destroy(Tp_*); + + size_type max_size() const; + + A2 select_on_container_copy_construction() const; +}; + +void test() +{ + using std::is_same; + using std::allocator_traits; + + typedef allocator_traits> at_A0; + typedef allocator_traits> at_A1; + typedef allocator_traits at_A2; + + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + +//XXX: Redundant, brings nothing new... + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); + VERIFY( (is_same::value) ); +#if 0 + VERIFY( (is_same, + A0>::value) ); + VERIFY( (is_same, + allocator_traits>>::value) ); + VERIFY( (is_same, + A1>::value) ); + VERIFY( (is_same, + allocator_traits>>::value) ); + VERIFY( (is_same, + test_type11>::value) ); + VERIFY( (is_same, + allocator_traits>::value) ); +#else + VERIFY( (is_same::other, + A0>::value) ); + VERIFY( (is_same::other, + allocator_traits>>::value) ); + VERIFY( (is_same::other, + A1>::value) ); + VERIFY( (is_same::other, + allocator_traits>>::value) ); + VERIFY( (is_same::other, + test_type11>::value) ); + VERIFY( (is_same::other, + allocator_traits>::value) ); +#endif +} + +int main() +{ + test(); + return 0; +} -- 1.7.1.1