From b821466067dd32988497bc8166fe0ae13f9a3b8e Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 30 May 2011 16:31:17 +0000 Subject: [PATCH] tuple: Implement uses-allocator construction. 2011-05-30 Jonathan Wakely * include/std/tuple: Implement uses-allocator construction. * include/bits/allocator.h (uses_allocator): Move to ... * include/bits/uses_allocator.h: New file. * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * testsuite/20_util/uses_allocator/cons_neg.cc: New. * testsuite/20_util/uses_allocator/construction.cc: New. * testsuite/20_util/tuple/cons/allocate_noncopyable.cc: New. * testsuite/20_util/tuple/cons/allocators.cc: New. From-SVN: r174443 --- libstdc++-v3/ChangeLog | 12 + libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/bits/allocator.h | 28 +- libstdc++-v3/include/bits/uses_allocator.h | 109 ++++++++ libstdc++-v3/include/std/tuple | 247 +++++++++++++++++- .../tuple/cons/allocate_noncopyable.cc | 73 ++++++ .../20_util/tuple/cons/allocators.cc | 169 ++++++++++++ .../20_util/uses_allocator/cons_neg.cc | 48 ++++ .../20_util/uses_allocator/construction.cc | 108 ++++++++ 10 files changed, 765 insertions(+), 31 deletions(-) create mode 100644 libstdc++-v3/include/bits/uses_allocator.h create mode 100644 libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc create mode 100644 libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc create mode 100644 libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc create mode 100644 libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1ddef589fa9..9875d6c6f42 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2011-05-30 Jonathan Wakely + + * include/std/tuple: Implement uses-allocator construction. + * include/bits/allocator.h (uses_allocator): Move to ... + * include/bits/uses_allocator.h: New file. + * include/Makefile.am: Add new header. + * include/Makefile.in: Regenerate. + * testsuite/20_util/uses_allocator/cons_neg.cc: New. + * testsuite/20_util/uses_allocator/construction.cc: New. + * testsuite/20_util/tuple/cons/allocate_noncopyable.cc: New. + * testsuite/20_util/tuple/cons/allocators.cc: New. + 2011-05-28 Jonathan Wakely * testsuite/20_util/pointer_traits/pointer_to.cc: Fix. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index d83678347d9..a4b7f27aaa4 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -168,6 +168,7 @@ bits_headers = \ ${bits_srcdir}/unique_ptr.h \ ${bits_srcdir}/unordered_map.h \ ${bits_srcdir}/unordered_set.h \ + ${bits_srcdir}/uses_allocator.h \ ${bits_srcdir}/valarray_array.h \ ${bits_srcdir}/valarray_array.tcc \ ${bits_srcdir}/valarray_before.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index fedba33196d..3cbe0e4500e 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -419,6 +419,7 @@ bits_headers = \ ${bits_srcdir}/unique_ptr.h \ ${bits_srcdir}/unordered_map.h \ ${bits_srcdir}/unordered_set.h \ + ${bits_srcdir}/uses_allocator.h \ ${bits_srcdir}/valarray_array.h \ ${bits_srcdir}/valarray_array.tcc \ ${bits_srcdir}/valarray_before.h \ diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index 37c6a596b91..6fccba51bb1 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -49,7 +49,7 @@ #ifdef __GXX_EXPERIMENTAL_CXX0X__ #include -#include // For _GLIBCXX_HAS_NESTED_TYPE +#include #include #endif @@ -207,32 +207,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; - - /// [allocator.tag] - struct allocator_arg_t { }; - - constexpr allocator_arg_t allocator_arg = allocator_arg_t(); - -_GLIBCXX_HAS_NESTED_TYPE(allocator_type) - - template::value> - struct __uses_allocator_helper - : public false_type { }; - - template - struct __uses_allocator_helper<_Tp, _Alloc, true> - : public integral_constant::value> - { }; - - /// [allocator.uses.trait] - template - struct uses_allocator - : public integral_constant::value> - { }; - template class __alloctr_rebind_helper { diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h new file mode 100644 index 00000000000..49b5409c15a --- /dev/null +++ b/libstdc++-v3/include/bits/uses_allocator.h @@ -0,0 +1,109 @@ +// Uses-allocator Construction -*- C++ -*- + +// Copyright (C) 2010, 2011 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 +// . + +#ifndef _USES_ALLOCATOR_H +#define _USES_ALLOCATOR_H 1 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// [allocator.tag] + struct allocator_arg_t { }; + + constexpr allocator_arg_t allocator_arg = allocator_arg_t(); + +_GLIBCXX_HAS_NESTED_TYPE(allocator_type) + + template::value> + struct __uses_allocator_helper + : public false_type { }; + + template + struct __uses_allocator_helper<_Tp, _Alloc, true> + : public integral_constant::value> + { }; + + /// [allocator.uses.trait] + template + struct uses_allocator + : public integral_constant::value> + { }; + + template + struct __uses_allocator_arg + : is_constructible<_Tp, _Alloc, _Args...> + { static_assert( uses_allocator<_Tp, _Alloc>::value, "uses allocator" ); }; + + struct __uses_alloc_base { }; + struct __uses_alloc0 : __uses_alloc_base + { struct _Anything { _Anything(...) { } } _M_a; }; + template + struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; + template + struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc; + + template + struct __uses_alloc + : conditional< + is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value, + __uses_alloc1<_Alloc>, + __uses_alloc2<_Alloc>>::type + { }; + + template + struct __uses_alloc + : __uses_alloc0 { }; + + template + struct __uses_alloc_impl + : __uses_alloc::value, _Tp, _Alloc, _Args...> + { }; + + template + __uses_alloc_impl<_Tp, _Alloc, _Args...> + __use_alloc(const _Alloc& __a) + { + __uses_alloc_impl<_Tp, _Alloc, _Args...> __ret; + __ret._M_a = &__a; + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index fee94e26e52..a0e9e694dc2 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -36,6 +36,7 @@ #else #include +#include namespace std _GLIBCXX_VISIBILITY(default) { @@ -81,10 +82,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Head_base(const _Head& __h) : _Head(__h) { } - template + template::value>::type> _Head_base(_UHead&& __h) : _Head(std::forward<_UHead>(__h)) { } + _Head_base(__uses_alloc0) + : _Head() { } + + template + _Head_base(__uses_alloc1<_Alloc> __a) + : _Head(allocator_arg, *__a._M_a) { } + + template + _Head_base(__uses_alloc2<_Alloc> __a) + : _Head(*__a._M_a) { } + + template + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } + _Head& _M_head() noexcept { return *this; } const _Head& _M_head() const noexcept { return *this; } }; @@ -98,10 +124,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Head_base(const _Head& __h) : _M_head_impl(__h) { } - template + template::value>::type> _Head_base(_UHead&& __h) : _M_head_impl(std::forward<_UHead>(__h)) { } + _Head_base(__uses_alloc0) + : _M_head_impl() { } + + template + _Head_base(__uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _Head_base(__uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + _Head& _M_head() noexcept { return _M_head_impl; } const _Head& _M_head() const noexcept { return _M_head_impl; } @@ -128,6 +180,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { template friend class _Tuple_impl; + _Tuple_impl() = default; + + template + _Tuple_impl(allocator_arg_t, const _Alloc&) { } + + template + _Tuple_impl(allocator_arg_t, const _Alloc&, const _Tuple_impl&) { } + + template + _Tuple_impl(allocator_arg_t, const _Alloc&, _Tuple_impl&&) { } + protected: void _M_swap(_Tuple_impl&) noexcept { /* no-op */ } }; @@ -160,7 +223,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) : _Inherited(__tail...), _Base(__head) { } - template + template::type> explicit _Tuple_impl(_UHead&& __head, _UTail&&... __tail) : _Inherited(std::forward<_UTail>(__tail)...), @@ -183,6 +247,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(std::move(__in._M_tail())), _Base(std::forward<_UHead>(__in._M_head())) { } + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a), + _Base(__use_alloc<_Head>(__a)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head, const _Tail&... __tail) + : _Inherited(__tag, __a, __tail...), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } + + template::type> + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head, _UTail&&... __tail) + : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Inherited(__tag, __a, __in._M_tail()), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + noexcept(std::is_nothrow_move_constructible<_Head>::value + && std::is_nothrow_move_constructible<_Inherited>::value) + : _Inherited(__tag, __a, std::move(__in._M_tail())), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(__in._M_head())) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(__tag, __a, __in._M_tail()), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __in._M_head()) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move(__in._M_tail())), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__in._M_head())) { } + _Tuple_impl& operator=(const _Tuple_impl& __in) { @@ -269,6 +381,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple(tuple<_UElements...>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } + // allocator-extended constructors + + template + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template::type> + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template::type> + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template::type> + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { } + tuple& operator=(const tuple& __in) { @@ -356,6 +513,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(std::forward<_U1>(__in.first), std::forward<_U2>(__in.second)) { } + // allocator-extended constructors + + template + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + tuple& operator=(const tuple& __in) { @@ -426,7 +629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Inherited(__a1) { } template::value>::type> + std::enable_if::value>::type> explicit tuple(_U1&& __a1) : _Inherited(std::forward<_U1>(__a1)) { } @@ -442,6 +645,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION tuple(tuple<_U1>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _U1>&&>(__in)) { } + // allocator-extended constructors + + template + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, const _T1& __a1) + : _Inherited(__tag, __a, __a1) { } + + // TODO: constrain for is_uses_allocator_constructible<_T1, _U1&&, _Alloc> + template + tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1) + : _Inherited(__tag, __a, std::forward<_U1>(__a1)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple<_U1>& __in) + : _Inherited(__tag, __a, static_cast&>(__in)) + { } + + template + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1>&&>(__in)) { } + tuple& operator=(const tuple& __in) { @@ -804,6 +1039,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const _Swallow_assign ignore{}; + /// Partial specialization for tuples + template + struct uses_allocator, _Alloc> : true_type { }; + /** * Stores a tuple of indices. Used by bind() to extract the elements * in a tuple. diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc new file mode 100644 index 00000000000..d729178b609 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/allocate_noncopyable.cc @@ -0,0 +1,73 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors + +#include +#include + +struct MyAlloc { }; + +struct Tag0 { }; +struct Tag1 { }; +struct Tag2 { }; + +// A non-copyable and non-movable type +struct Type +{ + typedef MyAlloc allocator_type; + + explicit Type(Tag0) { } + Type(std::allocator_arg_t, MyAlloc, Tag1) { } + Type(Tag2, MyAlloc) { } + + Type(const Type&) = delete; + Type(Type&&) = delete; + Type& operator=(const Type&) = delete; + Type& operator=(Type&&) = delete; +}; + +void test01() +{ + using std::allocator_arg; + using std::tuple; + + MyAlloc a; + Tag0 tag0; + Tag1 tag1; + Tag2 tag2; + + // N.B. cannot use Tag0 with uses-allocator construction, because + // uses_allocator is true but no suitable cosntructor + tuple t1(tag0); + + tuple t2(allocator_arg, a, tag1); + tuple t3(allocator_arg, a, tag2); + + tuple t4(allocator_arg, a, tag1, tag2); + + tuple t5(allocator_arg, a, tag2, tag1, tag2); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc new file mode 100644 index 00000000000..ae9dc8d7be2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/allocators.cc @@ -0,0 +1,169 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 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 +// . + +// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors + +#include +#include +#include + +struct MyAlloc { }; + +// type that can't be constructed with an allocator +struct CannotUse +{ + CannotUse(int = 0, int = 0) : ok(true) { } + + bool ok; +}; + +// type that can be constructed with an allocator +// but which has uses_allocator == false +struct DoesNotUse +{ + typedef MyAlloc allocator_type; + + DoesNotUse(int = 0) : ok(true) { } + DoesNotUse(std::allocator_arg_t, MyAlloc, int = 0) : ok(false) { } + DoesNotUse(MyAlloc) : ok(false) { } + DoesNotUse(int, MyAlloc) : ok(false) { } + + DoesNotUse(const DoesNotUse&) : ok(true) { } + DoesNotUse(std::allocator_arg_t, MyAlloc, const DoesNotUse&) : ok(false) { } + DoesNotUse(const DoesNotUse&, MyAlloc) : ok(false) { } + + DoesNotUse(DoesNotUse&&) : ok(true) { } + DoesNotUse(std::allocator_arg_t, MyAlloc, DoesNotUse&&) : ok(false) { } + DoesNotUse(DoesNotUse&&, MyAlloc) : ok(false) { } + + bool ok; +}; + +namespace std +{ + template + struct uses_allocator : false_type { }; +} + +// type that can be constructed with an allocator as second argument +struct UsesWithTag +{ + typedef MyAlloc allocator_type; + + UsesWithTag(int = 0) : ok(false) { } + UsesWithTag(std::allocator_arg_t, MyAlloc, int = 0) : ok(true) { } + UsesWithTag(MyAlloc) : ok(false) { } + UsesWithTag(int, MyAlloc) : ok(false) { } + + UsesWithTag(const UsesWithTag&) : ok(false) { } + UsesWithTag(std::allocator_arg_t, MyAlloc, const UsesWithTag&) : ok(true) { } + UsesWithTag(const UsesWithTag&, MyAlloc) : ok(false) { } + + UsesWithTag(UsesWithTag&&) : ok(false) { } + UsesWithTag(std::allocator_arg_t, MyAlloc, UsesWithTag&&) : ok(true) { } + UsesWithTag(UsesWithTag&&, MyAlloc) : ok(false) { } + + bool ok; +}; + +// type that can be constructed with an allocator as last argument +struct UsesWithoutTag +{ + typedef MyAlloc allocator_type; + + UsesWithoutTag(int = 0) : ok(false) { } + UsesWithoutTag(MyAlloc) : ok(true) { } + UsesWithoutTag(int, MyAlloc) : ok(true) { } + + UsesWithoutTag(const UsesWithoutTag&) : ok(false) { } + UsesWithoutTag(const UsesWithoutTag&, MyAlloc) : ok(true) { } + + UsesWithoutTag(UsesWithoutTag&&) : ok(false) { } + UsesWithoutTag(UsesWithoutTag&&, MyAlloc) : ok(true) { } + + bool ok; +}; + +void test01() +{ + bool test __attribute__((unused)) = true; + using std::allocator_arg; + using std::tuple; + using std::make_tuple; + using std::get; + + typedef CannotUse T1; + typedef DoesNotUse T2; + typedef UsesWithTag T3; + typedef UsesWithoutTag T4; + typedef tuple test_type; + + MyAlloc a; + + // default construction + test_type t1(allocator_arg, a); + VERIFY( get<0>(t1).ok ); + VERIFY( get<1>(t1).ok ); + VERIFY( get<2>(t1).ok ); + VERIFY( get<3>(t1).ok ); + + // copy construction + test_type t2(allocator_arg, a, t1); + VERIFY( get<0>(t2).ok ); + VERIFY( get<1>(t2).ok ); + VERIFY( get<2>(t2).ok ); + VERIFY( get<3>(t2).ok ); + + // move construction + test_type t3(allocator_arg, a, std::move(t1)); + VERIFY( get<0>(t3).ok ); + VERIFY( get<1>(t3).ok ); + VERIFY( get<2>(t3).ok ); + VERIFY( get<3>(t3).ok ); + + // construction from int + test_type t4(allocator_arg, a, 1, 2, 3, 4); + VERIFY( get<0>(t4).ok ); + VERIFY( get<1>(t4).ok ); + VERIFY( get<2>(t4).ok ); + VERIFY( get<3>(t4).ok ); + + auto ints = make_tuple(1, 2, 3, 4); + + // construction from lvalue tuple of ints + test_type t5(allocator_arg, a, ints); + VERIFY( get<0>(t5).ok ); + VERIFY( get<1>(t5).ok ); + VERIFY( get<2>(t5).ok ); + VERIFY( get<3>(t2).ok ); + + // construction from rvalue tuple of ints + test_type t6(allocator_arg, a, std::move(ints)); + VERIFY( get<0>(t6).ok ); + VERIFY( get<1>(t6).ok ); + VERIFY( get<2>(t6).ok ); + VERIFY( get<3>(t6).ok ); + +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc new file mode 100644 index 00000000000..b6b706c67eb --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +// 20.4.2.1 [tuple.cnstr] Allocator-extended constructors + +#include +#include + +struct MyAlloc { }; + +struct Type +{ + typedef MyAlloc allocator_type; // uses_allocator is true + + explicit Type(int) { } + + Type(std::allocator_arg_t, MyAlloc) { } + Type(MyAlloc) { } +}; + +void test01() +{ + using std::allocator_arg; + using std::tuple; + + MyAlloc a; + + tuple t(allocator_arg, a, 1); +} +// { dg-error "no matching function" "" { target *-*-* } 112 } +// { dg-excess-errors "note" } diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc new file mode 100644 index 00000000000..94fca79c252 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/uses_allocator/construction.cc @@ -0,0 +1,108 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 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 +// . + +// 20.6.7.2 uses-allocator construction + +#include +#include +#include + +struct MyAlloc { }; + +// type that can't be constructed with an allocator +struct CannotUse +{ + CannotUse(int) : ok(true) { } + + bool ok; +}; + +// type that can be constructed with an allocator +// but which has uses_allocator == false +struct DoesNotUse +{ + typedef MyAlloc allocator_type; + + DoesNotUse(int) : ok(true) { } + DoesNotUse(std::allocator_arg_t, MyAlloc, int) : ok(false) { } + DoesNotUse(int, MyAlloc) : ok(false) { } + + bool ok; +}; + +namespace std +{ + template + struct uses_allocator : false_type { }; +} + +// type that can be constructed with an allocator as second argument +struct UsesWithTag +{ + typedef MyAlloc allocator_type; + + UsesWithTag(int) : ok(false) { } + UsesWithTag(std::allocator_arg_t, MyAlloc, int) : ok(true) { } + UsesWithTag(int, MyAlloc) : ok(false) { } + + bool ok; +}; + +// type that can be constructed with an allocator as last argument +struct UsesWithoutTag +{ + typedef MyAlloc allocator_type; + + UsesWithoutTag(int) : ok(false) { } + UsesWithoutTag(int, MyAlloc) : ok(true) { } + + bool ok; +}; + + +template + bool test2(T... args) + { + using std::allocator_arg; + using std::tuple; + using std::get; + + tuple t(allocator_arg, MyAlloc(), 1, args...); + + return get<0>(t).ok; + } + +template + void test(T... args) + { + bool test __attribute__((unused)) = true; + + VERIFY( test2(args...) ); + VERIFY( test2(args...) ); + VERIFY( test2(args...) ); + VERIFY( test2(args...) ); + } + +int main() +{ + test(); + test(1); + test(1, 2); + return 0; +} -- 2.30.2