libstdc++: Implement P1518R2 for container deduction guides
This implements the C++23 P1518R2 proposal "Stop overconstraining allocators in container deduction guides" as a fix for C++17 and C++20 too. The changes allow class template argument deduction to ignore the type of a constructor argument that initializes an allocator_type parameter if the type should be deducible only from the other arguments. So for the constructor vector(const vector&, const allocator_type&) only the first argument is used for deduction, allowing the second argument to be anything that is implicitly convertible to argument_type. Previously deduction would fail or an ill-formed type would be deduced if the second argument wasn't of type allocator_type. The unordered containers do not need changes, because their allocator-extended constructors use the allocator_type alias, which comes from the dependent base class so is already a non-deduced context. libstdc++-v3/ChangeLog: * include/bits/forward_list.h (forward_list): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/bits/stl_bvector.h (vector<bool>): Likewise. * include/bits/stl_deque.h (deque): Likewise. * include/bits/stl_list.h (list): Likewise. * include/bits/stl_map.h (map): Likewise. * include/bits/stl_multimap.h (multimap): Likewise. * include/bits/stl_multiset.h (multiset): Likewise. * include/bits/stl_set.h (set): Likewise. * include/bits/stl_vector.h (vector): Likewise. * include/bits/stl_queue.h (queue, priority_queue): Do not constrain Allocator template parameter of deduction guides that have a Container parameter. * include/bits/stl_stack.h (stack): Likewise. * include/debug/deque (__gnu_debug::deque): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/debug/list (__gnu_debug::list): Likewise. * include/debug/map.h (__gnu_debug::map): Likewise. * include/debug/multimap.h (__gnu_debug::multimap): Likewise. * include/debug/multiset.h (__gnu_debug::multiset): Likewise. * include/debug/set.h (__gnu_debug::set): Likewise. * include/debug/vector (__gnu_debug::vector): Likewise. * testsuite/23_containers/deque/cons/deduction.cc: Test class template argument deduction with non-deduced allocator arguments. * testsuite/23_containers/forward_list/cons/deduction.cc: Likewise. * testsuite/23_containers/list/cons/deduction.cc: Likewise. * testsuite/23_containers/map/cons/deduction.cc: Likewise. * testsuite/23_containers/multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/priority_queue/deduction.cc: Likewise. * testsuite/23_containers/queue/deduction.cc: Likewise. * testsuite/23_containers/set/cons/deduction.cc: Likewise. * testsuite/23_containers/stack/deduction.cc: Likewise. * testsuite/23_containers/unordered_map/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_set/cons/deduction.cc: Likewise. * testsuite/23_containers/vector/cons/deduction.cc: Likewise.
This commit is contained in:
parent
728e639d82
commit
22d34a2a50
33 changed files with 568 additions and 39 deletions
|
@ -480,7 +480,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
* @param __list Input list to copy.
|
||||
* @param __al An allocator object.
|
||||
*/
|
||||
forward_list(const forward_list& __list, const _Alloc& __al)
|
||||
forward_list(const forward_list& __list,
|
||||
const __type_identity_t<_Alloc>& __al)
|
||||
: _Base(_Node_alloc_type(__al))
|
||||
{ _M_range_initialize(__list.begin(), __list.end()); }
|
||||
|
||||
|
@ -508,7 +509,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
* @param __list Input list to move.
|
||||
* @param __al An allocator object.
|
||||
*/
|
||||
forward_list(forward_list&& __list, const _Alloc& __al)
|
||||
forward_list(forward_list&& __list,
|
||||
const __type_identity_t<_Alloc>& __al)
|
||||
noexcept(_Node_alloc_traits::_S_always_equal())
|
||||
: forward_list(std::move(__list), _Node_alloc_type(__al),
|
||||
typename _Node_alloc_traits::is_always_equal{})
|
||||
|
|
|
@ -706,13 +706,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
}
|
||||
|
||||
public:
|
||||
vector(vector&& __x, const allocator_type& __a)
|
||||
vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(_Bit_alloc_traits::_S_always_equal())
|
||||
: vector(std::move(__x), __a,
|
||||
typename _Bit_alloc_traits::is_always_equal{})
|
||||
{ }
|
||||
|
||||
vector(const vector& __x, const allocator_type& __a)
|
||||
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__a)
|
||||
{
|
||||
_M_initialize(__x.size());
|
||||
|
|
|
@ -932,14 +932,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
deque(deque&&) = default;
|
||||
|
||||
/// Copy constructor with alternative allocator
|
||||
deque(const deque& __x, const allocator_type& __a)
|
||||
deque(const deque& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__a, __x.size())
|
||||
{ std::__uninitialized_copy_a(__x.begin(), __x.end(),
|
||||
this->_M_impl._M_start,
|
||||
_M_get_Tp_allocator()); }
|
||||
|
||||
/// Move constructor with alternative allocator
|
||||
deque(deque&& __x, const allocator_type& __a)
|
||||
deque(deque&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{})
|
||||
{ }
|
||||
|
||||
|
|
|
@ -836,7 +836,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
: _Base(_Node_alloc_type(__a))
|
||||
{ _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
|
||||
|
||||
list(const list& __x, const allocator_type& __a)
|
||||
list(const list& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(_Node_alloc_type(__a))
|
||||
{ _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
|
||||
|
||||
|
@ -856,7 +856,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|||
}
|
||||
|
||||
public:
|
||||
list(list&& __x, const allocator_type& __a)
|
||||
list(list&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(_Node_alloc_traits::_S_always_equal())
|
||||
: list(std::move(__x), __a,
|
||||
typename _Node_alloc_traits::is_always_equal{})
|
||||
|
|
|
@ -237,11 +237,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
: _M_t(_Pair_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended copy constructor.
|
||||
map(const map& __m, const allocator_type& __a)
|
||||
map(const map& __m, const __type_identity_t<allocator_type>& __a)
|
||||
: _M_t(__m._M_t, _Pair_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended move constructor.
|
||||
map(map&& __m, const allocator_type& __a)
|
||||
map(map&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(is_nothrow_copy_constructible<_Compare>::value
|
||||
&& _Alloc_traits::_S_always_equal())
|
||||
: _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }
|
||||
|
|
|
@ -234,11 +234,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
: _M_t(_Pair_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended copy constructor.
|
||||
multimap(const multimap& __m, const allocator_type& __a)
|
||||
multimap(const multimap& __m,
|
||||
const __type_identity_t<allocator_type>& __a)
|
||||
: _M_t(__m._M_t, _Pair_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended move constructor.
|
||||
multimap(multimap&& __m, const allocator_type& __a)
|
||||
multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(is_nothrow_copy_constructible<_Compare>::value
|
||||
&& _Alloc_traits::_S_always_equal())
|
||||
: _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { }
|
||||
|
|
|
@ -248,11 +248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
: _M_t(_Key_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended copy constructor.
|
||||
multiset(const multiset& __m, const allocator_type& __a)
|
||||
multiset(const multiset& __m,
|
||||
const __type_identity_t<allocator_type>& __a)
|
||||
: _M_t(__m._M_t, _Key_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended move constructor.
|
||||
multiset(multiset&& __m, const allocator_type& __a)
|
||||
multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(is_nothrow_copy_constructible<_Compare>::value
|
||||
&& _Alloc_traits::_S_always_equal())
|
||||
: _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { }
|
||||
|
|
|
@ -342,8 +342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
queue(_Container) -> queue<typename _Container::value_type, _Container>;
|
||||
|
||||
template<typename _Container, typename _Allocator,
|
||||
typename = _RequireNotAllocator<_Container>,
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
typename = _RequireNotAllocator<_Container>>
|
||||
queue(_Container, _Allocator)
|
||||
-> queue<typename _Container::value_type, _Container>;
|
||||
|
||||
|
@ -817,8 +816,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Compare, typename _Container, typename _Allocator,
|
||||
typename = _RequireNotAllocator<_Compare>,
|
||||
typename = _RequireNotAllocator<_Container>,
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
typename = _RequireNotAllocator<_Container>>
|
||||
priority_queue(_Compare, _Container, _Allocator)
|
||||
-> priority_queue<typename _Container::value_type, _Container, _Compare>;
|
||||
#endif
|
||||
|
|
|
@ -252,11 +252,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
: _M_t(_Key_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended copy constructor.
|
||||
set(const set& __x, const allocator_type& __a)
|
||||
set(const set& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _M_t(__x._M_t, _Key_alloc_type(__a)) { }
|
||||
|
||||
/// Allocator-extended move constructor.
|
||||
set(set&& __x, const allocator_type& __a)
|
||||
set(set&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(is_nothrow_copy_constructible<_Compare>::value
|
||||
&& _Alloc_traits::_S_always_equal())
|
||||
: _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { }
|
||||
|
|
|
@ -317,8 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
stack(_Container) -> stack<typename _Container::value_type, _Container>;
|
||||
|
||||
template<typename _Container, typename _Allocator,
|
||||
typename = _RequireNotAllocator<_Container>,
|
||||
typename = _RequireAllocator<_Allocator>>
|
||||
typename = _RequireNotAllocator<_Container>>
|
||||
stack(_Container, _Allocator)
|
||||
-> stack<typename _Container::value_type, _Container>;
|
||||
|
||||
|
|
|
@ -572,7 +572,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
vector(vector&&) noexcept = default;
|
||||
|
||||
/// Copy constructor with alternative allocator
|
||||
vector(const vector& __x, const allocator_type& __a)
|
||||
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__x.size(), __a)
|
||||
{
|
||||
this->_M_impl._M_finish =
|
||||
|
@ -604,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
|||
|
||||
public:
|
||||
/// Move constructor with alternative allocator
|
||||
vector(vector&& __rv, const allocator_type& __m)
|
||||
vector(vector&& __rv, const __type_identity_t<allocator_type>& __m)
|
||||
noexcept( noexcept(
|
||||
vector(std::declval<vector&&>(), std::declval<const allocator_type&>(),
|
||||
std::declval<typename _Alloc_traits::is_always_equal>())) )
|
||||
|
|
|
@ -108,10 +108,10 @@ namespace __debug
|
|||
deque(const deque&) = default;
|
||||
deque(deque&&) = default;
|
||||
|
||||
deque(const deque& __d, const _Allocator& __a)
|
||||
deque(const deque& __d, const __type_identity_t<_Allocator>& __a)
|
||||
: _Base(__d, __a) { }
|
||||
|
||||
deque(deque&& __d, const _Allocator& __a)
|
||||
deque(deque&& __d, const __type_identity_t<_Allocator>& __a)
|
||||
: _Safe(std::move(__d)), _Base(std::move(__d), __a) { }
|
||||
|
||||
deque(initializer_list<value_type> __l,
|
||||
|
|
|
@ -115,10 +115,10 @@ namespace __debug
|
|||
|
||||
~list() = default;
|
||||
|
||||
list(const list& __x, const allocator_type& __a)
|
||||
list(const list& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__x, __a) { }
|
||||
|
||||
list(list&& __x, const allocator_type& __a)
|
||||
list(list&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(
|
||||
std::is_nothrow_constructible<_Base,
|
||||
_Base, const allocator_type&>::value )
|
||||
|
|
|
@ -114,10 +114,10 @@ namespace __debug
|
|||
map(const allocator_type& __a)
|
||||
: _Base(__a) { }
|
||||
|
||||
map(const map& __m, const allocator_type& __a)
|
||||
map(const map& __m, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__m, __a) { }
|
||||
|
||||
map(map&& __m, const allocator_type& __a)
|
||||
map(map&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
|
||||
: _Safe(std::move(__m._M_safe()), __a),
|
||||
_Base(std::move(__m._M_base()), __a) { }
|
||||
|
|
|
@ -114,10 +114,11 @@ namespace __debug
|
|||
multimap(const allocator_type& __a)
|
||||
: _Base(__a) { }
|
||||
|
||||
multimap(const multimap& __m, const allocator_type& __a)
|
||||
multimap(const multimap& __m,
|
||||
const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__m, __a) { }
|
||||
|
||||
multimap(multimap&& __m, const allocator_type& __a)
|
||||
multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
|
||||
: _Safe(std::move(__m._M_safe()), __a),
|
||||
_Base(std::move(__m._M_base()), __a) { }
|
||||
|
|
|
@ -113,10 +113,11 @@ namespace __debug
|
|||
multiset(const allocator_type& __a)
|
||||
: _Base(__a) { }
|
||||
|
||||
multiset(const multiset& __m, const allocator_type& __a)
|
||||
multiset(const multiset& __m,
|
||||
const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__m, __a) { }
|
||||
|
||||
multiset(multiset&& __m, const allocator_type& __a)
|
||||
multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) )
|
||||
: _Safe(std::move(__m._M_safe()), __a),
|
||||
_Base(std::move(__m._M_base()), __a) { }
|
||||
|
|
|
@ -113,10 +113,10 @@ namespace __debug
|
|||
set(const allocator_type& __a)
|
||||
: _Base(__a) { }
|
||||
|
||||
set(const set& __x, const allocator_type& __a)
|
||||
set(const set& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__x, __a) { }
|
||||
|
||||
set(set&& __x, const allocator_type& __a)
|
||||
set(set&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept( noexcept(_Base(std::move(__x._M_base()), __a)) )
|
||||
: _Safe(std::move(__x._M_safe()), __a),
|
||||
_Base(std::move(__x._M_base()), __a) { }
|
||||
|
|
|
@ -212,10 +212,10 @@ namespace __debug
|
|||
vector(const vector&) = default;
|
||||
vector(vector&&) = default;
|
||||
|
||||
vector(const vector& __x, const allocator_type& __a)
|
||||
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
|
||||
: _Base(__x, __a) { }
|
||||
|
||||
vector(vector&& __x, const allocator_type& __a)
|
||||
vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
|
||||
noexcept(
|
||||
std::is_nothrow_constructible<_Base,
|
||||
_Base, const allocator_type&>::value )
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <deque>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T>
|
||||
using input_iterator_seq
|
||||
|
@ -67,3 +68,31 @@ test02()
|
|||
std::deque s4(1U, 2L, std::allocator<long>());
|
||||
check_type<std::deque<long>>(s4);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Deque = std::deque<unsigned, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
Deque d(p);
|
||||
|
||||
std::deque s1(d, p);
|
||||
check_type<Deque>(s1);
|
||||
|
||||
std::deque s2(std::move(d), p);
|
||||
check_type<Deque>(s2);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <forward_list>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T>
|
||||
using input_iterator_seq
|
||||
|
@ -67,3 +68,31 @@ test02()
|
|||
std::forward_list s4(1U, 2L, std::allocator<long>());
|
||||
check_type<std::forward_list<long>>(s4);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Flist = std::forward_list<unsigned, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
Flist f(p);
|
||||
|
||||
std::forward_list s1(f, p);
|
||||
check_type<Flist>(s1);
|
||||
|
||||
std::forward_list s2(std::move(f), p);
|
||||
check_type<Flist>(s2);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <list>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T>
|
||||
using input_iterator_seq
|
||||
|
@ -67,3 +68,31 @@ test02()
|
|||
std::list s4(1U, 2L, std::allocator<long>());
|
||||
check_type<std::list<long>>(s4);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using List = std::list<unsigned, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
List l(p);
|
||||
|
||||
std::list s1(l, p);
|
||||
check_type<List>(s1);
|
||||
|
||||
std::list s2(std::move(l), p);
|
||||
check_type<List>(s2);
|
||||
}
|
||||
|
|
|
@ -222,3 +222,39 @@ void h()
|
|||
std::map<int, double, std::less<int>,
|
||||
SimpleAllocator<value_type>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
|
||||
using Map = std::map<unsigned, void*, std::greater<>, PairAlloc>;
|
||||
Pool* p = nullptr;
|
||||
Map m(p);
|
||||
|
||||
std::map s1(m, p);
|
||||
check_type<Map>(s1);
|
||||
|
||||
std::map s2(std::move(m), p);
|
||||
check_type<Map>(s2);
|
||||
}
|
||||
|
|
|
@ -174,3 +174,39 @@ void h()
|
|||
std::multimap<int, double, std::less<int>,
|
||||
SimpleAllocator<value_type>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
|
||||
using MMap = std::multimap<unsigned, void*, std::greater<>, PairAlloc>;
|
||||
Pool* p = nullptr;
|
||||
MMap m(p);
|
||||
|
||||
std::multimap s1(m, p);
|
||||
check_type<MMap>(s1);
|
||||
|
||||
std::multimap s2(std::move(m), p);
|
||||
check_type<MMap>(s2);
|
||||
}
|
||||
|
|
|
@ -130,3 +130,38 @@ void g()
|
|||
std::multiset<int, std::less<int>,
|
||||
SimpleAllocator<value_type>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using MSet = std::multiset<unsigned, std::greater<>, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
MSet s(p);
|
||||
|
||||
std::multiset s1(s, p);
|
||||
check_type<MSet>(s1);
|
||||
|
||||
std::multiset s2(std::move(s), p);
|
||||
check_type<MSet>(s2);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <deque>
|
||||
#include <vector>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
@ -116,3 +117,39 @@ test02()
|
|||
std::priority_queue s14(seq.begin(), seq.end(), cmp, std::deque<short>{});
|
||||
check_type<std::priority_queue<short, std::deque<short>, Cmp>>(s14);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Vector = std::vector<short, Alloc<short>>;
|
||||
using Cmp = std::greater<long>;
|
||||
Pool* p = nullptr;
|
||||
Vector v(p);
|
||||
Cmp cmp;
|
||||
|
||||
std::priority_queue q1(cmp, v, p);
|
||||
check_type<std::priority_queue<short, Vector, Cmp>>(q1);
|
||||
|
||||
std::priority_queue q2(cmp, std::move(v), p);
|
||||
check_type<std::priority_queue<short, Vector, Cmp>>(q2);
|
||||
|
||||
std::priority_queue q3(q1, p);
|
||||
check_type<std::priority_queue<short, Vector, Cmp>>(q3);
|
||||
|
||||
std::priority_queue q4(std::move(q1), p);
|
||||
check_type<std::priority_queue<short, Vector, Cmp>>(q4);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <queue>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
@ -86,3 +87,36 @@ test02()
|
|||
std::queue s8(std::move(l), l.get_allocator());
|
||||
check_type<std::queue<long, std::list<long>>>(s8);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Deque = std::deque<unsigned, Alloc<unsigned>>;
|
||||
using List = std::list<long, Alloc<long>>;
|
||||
Pool* p = nullptr;
|
||||
Deque d(p);
|
||||
List l(p);
|
||||
|
||||
std::queue q1(d, p);
|
||||
check_type<std::queue<unsigned, Deque>>(q1);
|
||||
|
||||
std::queue q2(l, p);
|
||||
check_type<std::queue<long, List>>(q2);
|
||||
|
||||
std::queue q3(q2, p);
|
||||
check_type<std::queue<long, List>>(q3);
|
||||
}
|
||||
|
|
|
@ -131,3 +131,38 @@ void g()
|
|||
std::set<int, std::less<int>,
|
||||
SimpleAllocator<value_type>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Set = std::set<unsigned, std::greater<>, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
Set s(p);
|
||||
|
||||
std::set s1(s, p);
|
||||
check_type<Set>(s1);
|
||||
|
||||
std::set s2(std::move(s), p);
|
||||
check_type<Set>(s2);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <stack>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
@ -58,7 +59,7 @@ test01()
|
|||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
{
|
||||
std::deque<unsigned> d;
|
||||
std::list<long> l;
|
||||
|
||||
|
|
|
@ -124,3 +124,41 @@ void f()
|
|||
std::equal_to<int>,
|
||||
SimpleAllocator<std::pair<const int, double>>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
|
||||
using Hash = std::hash<unsigned long>;
|
||||
using Eq = std::equal_to<>;
|
||||
using UMap = std::unordered_map<unsigned, void*, Hash, Eq, PairAlloc>;
|
||||
Pool* p = nullptr;
|
||||
UMap m(p);
|
||||
|
||||
std::unordered_map s1(m, p);
|
||||
check_type<UMap>(s1);
|
||||
|
||||
std::unordered_map s2(std::move(m), p);
|
||||
check_type<UMap>(s2);
|
||||
}
|
||||
|
|
|
@ -133,3 +133,41 @@ void f()
|
|||
std::equal_to<int>,
|
||||
SimpleAllocator<std::pair<const int, double>>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using PairAlloc = Alloc<std::pair<const unsigned, void*>>;
|
||||
using Hash = std::hash<unsigned long>;
|
||||
using Eq = std::equal_to<>;
|
||||
using UMMap = std::unordered_multimap<unsigned, void*, Hash, Eq, PairAlloc>;
|
||||
Pool* p = nullptr;
|
||||
UMMap m(p);
|
||||
|
||||
std::unordered_multimap s1(m, p);
|
||||
check_type<UMMap>(s1);
|
||||
|
||||
std::unordered_multimap s2(std::move(m), p);
|
||||
check_type<UMMap>(s2);
|
||||
}
|
||||
|
|
|
@ -142,3 +142,40 @@ void f()
|
|||
std::equal_to<int>,
|
||||
SimpleAllocator<int>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Hash = std::hash<unsigned long>;
|
||||
using Eq = std::equal_to<>;
|
||||
using UMSet = std::unordered_multiset<unsigned, Hash, Eq, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
UMSet s(p);
|
||||
|
||||
std::unordered_multiset s1(s, p);
|
||||
check_type<UMSet>(s1);
|
||||
|
||||
std::unordered_multiset s2(std::move(s), p);
|
||||
check_type<UMSet>(s2);
|
||||
}
|
||||
|
|
|
@ -137,3 +137,40 @@ void f()
|
|||
std::equal_to<int>,
|
||||
SimpleAllocator<int>>>);
|
||||
}
|
||||
|
||||
template<typename T, typename U> struct require_same;
|
||||
template<typename T> struct require_same<T, T> { using type = void; };
|
||||
|
||||
template<typename T, typename U>
|
||||
typename require_same<T, U>::type
|
||||
check_type(U&) { }
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Hash = std::hash<unsigned long>;
|
||||
using Eq = std::equal_to<>;
|
||||
using USet = std::unordered_set<unsigned, Hash, Eq, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
USet s(p);
|
||||
|
||||
std::unordered_set s1(s, p);
|
||||
check_type<USet>(s1);
|
||||
|
||||
std::unordered_set s2(std::move(s), p);
|
||||
check_type<USet>(s2);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include <testsuite_iterators.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
template<typename T>
|
||||
using input_iterator_seq
|
||||
|
@ -49,6 +50,24 @@ test01()
|
|||
check_type<const std::vector<unsigned>>(s4);
|
||||
}
|
||||
|
||||
void
|
||||
test01b()
|
||||
{
|
||||
std::vector<bool> s0;
|
||||
|
||||
std::vector s1 = s0;
|
||||
check_type<std::vector<bool>>(s1);
|
||||
|
||||
std::vector s2 = std::move(s0);
|
||||
check_type<std::vector<bool>>(s2);
|
||||
|
||||
const std::vector s3 = s0;
|
||||
check_type<const std::vector<bool>>(s3);
|
||||
|
||||
const std::vector s4 = s3;
|
||||
check_type<const std::vector<bool>>(s4);
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
|
@ -67,3 +86,59 @@ test02()
|
|||
std::vector s4(1U, 2L, std::allocator<long>());
|
||||
check_type<std::vector<long>>(s4);
|
||||
}
|
||||
|
||||
void
|
||||
test02b()
|
||||
{
|
||||
bool a[1] = {};
|
||||
input_iterator_seq<bool> seq(a);
|
||||
|
||||
std::vector s1(seq.begin(), seq.end());
|
||||
check_type<std::vector<bool>>(s1);
|
||||
|
||||
std::vector s2(seq.begin(), seq.end(), std::allocator<bool>());
|
||||
check_type<std::vector<bool>>(s2);
|
||||
|
||||
std::vector s3(1U, true);
|
||||
check_type<std::vector<bool>>(s3);
|
||||
|
||||
std::vector s4(1U, true, std::allocator<bool>());
|
||||
check_type<std::vector<bool>>(s4);
|
||||
}
|
||||
|
||||
struct Pool;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : __gnu_test::SimpleAllocator<T>
|
||||
{
|
||||
Alloc(Pool*) { }
|
||||
|
||||
template<typename U>
|
||||
Alloc(const Alloc<U>&) { }
|
||||
};
|
||||
|
||||
void
|
||||
test_p1518r2()
|
||||
{
|
||||
// P1518R2 - Stop overconstraining allocators in container deduction guides.
|
||||
// This is a C++23 feature but we support it for C++17 too.
|
||||
|
||||
using Vector = std::vector<unsigned, Alloc<unsigned>>;
|
||||
Pool* p = nullptr;
|
||||
Vector v(p);
|
||||
|
||||
std::vector s1(v, p);
|
||||
check_type<Vector>(s1);
|
||||
|
||||
std::vector s2(std::move(v), p);
|
||||
check_type<Vector>(s2);
|
||||
|
||||
using BVector = std::vector<bool, Alloc<bool>>;
|
||||
BVector b(p);
|
||||
|
||||
std::vector s3(b, p);
|
||||
check_type<BVector>(s3);
|
||||
|
||||
std::vector s4(std::move(b), p);
|
||||
check_type<BVector>(s4);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue