.. note::
- .. [#note-P0433] P0433: The only part not fully implemented is the requirement that certain deduction guides should not participate in overload resolution when given incorrect template arguments.
.. [#note-P0607] P0607: The parts of P0607 that are not done are the ``<regex>`` bits.
"`P0298R3 <https://wg21.link/P0298R3>`__","CWG","A byte type definition","Kona","|Complete|","5.0"
"`P0317R1 <https://wg21.link/P0317R1>`__","LWG","Directory Entry Caching for Filesystem","Kona","|Complete|","7.0"
"`P0430R2 <https://wg21.link/P0430R2>`__","LWG","File system library on non-POSIX-like operating systems","Kona","|Complete|","7.0"
-"`P0433R2 <https://wg21.link/P0433R2>`__","LWG","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","Kona","|In Progress| [#note-P0433]_","7.0"
+"`P0433R2 <https://wg21.link/P0433R2>`__","LWG","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","Kona","|Complete|","14.0"
"`P0452R1 <https://wg21.link/P0452R1>`__","LWG","Unifying <numeric> Parallel Algorithms","Kona","",""
"`P0467R2 <https://wg21.link/P0467R2>`__","LWG","Iterator Concerns for Parallel Algorithms","Kona","",""
"`P0492R2 <https://wg21.link/P0492R2>`__","LWG","Proposed Resolution of C++17 National Body Comments for Filesystems","Kona","|Complete|","7.0"
}
};
+// A version of `allocator_traits` for internal usage that SFINAEs away if the
+// given allocator doesn't have a nested `value_type`. This helps avoid hard
+// errors when forming implicit deduction guides for a container that has an
+// invalid Allocator type. See https://wg21.link/LWGXXXXX.
+// TODO(varconst): use the actual link once available.
+template <class _Alloc, class _ValueType = typename _Alloc::value_type>
+struct _LIBCPP_TEMPLATE_VIS __allocator_traits : allocator_traits<_Alloc> {};
+
template <class _Traits, class _Tp>
struct __rebind_alloc_helper {
#ifndef _LIBCPP_CXX03_LANG
template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
deque(InputIterator, InputIterator, Allocator = Allocator())
- -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
+ -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17
template <class T, class Allocator>
bool operator==(const deque<T,Allocator>& x, const deque<T,Allocator>& y);
#include <__config>
#include <__debug>
+#include <__iterator/iterator_traits.h>
#include <__split_buffer>
#include <__utility/forward.h>
#include <algorithm>
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
"Allocator::value_type must be same type as value_type");
- typedef __deque_base<value_type, allocator_type> __base;
+ typedef __deque_base<value_type, allocator_type> __base;
- typedef typename __base::__alloc_traits __alloc_traits;
- typedef typename __base::reference reference;
- typedef typename __base::const_reference const_reference;
- typedef typename __base::iterator iterator;
- typedef typename __base::const_iterator const_iterator;
- typedef typename __base::size_type size_type;
- typedef typename __base::difference_type difference_type;
+ typedef typename __base::__alloc_traits __alloc_traits;
+ typedef typename __base::reference reference;
+ typedef typename __base::const_reference const_reference;
+ typedef typename __base::iterator iterator;
+ typedef typename __base::const_iterator const_iterator;
+ typedef typename __allocator_traits<allocator_type>::size_type size_type;
+ typedef typename __base::difference_type difference_type;
- typedef typename __base::pointer pointer;
- typedef typename __base::const_pointer const_pointer;
- typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
- typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef typename __base::pointer pointer;
+ typedef typename __base::const_pointer const_pointer;
+ typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
+ typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
using typename __base::__deque_range;
using typename __base::__deque_block_range;
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator,
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
deque(_InputIterator, _InputIterator)
template<class _InputIterator,
class _Alloc,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
deque(_InputIterator, _InputIterator, _Alloc)
-> deque<__iter_value_type<_InputIterator>, _Alloc>;
#endif
-
template <class _Tp, class _Allocator>
deque<_Tp, _Allocator>::deque(size_type __n)
{
typedef const value_type& const_reference;
typedef typename allocator_traits<allocator_type>::pointer pointer;
typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
- typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename __allocator_traits<allocator_type>::size_type size_type;
typedef typename allocator_traits<allocator_type>::difference_type difference_type;
typedef typename base::iterator iterator;
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator,
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
forward_list(_InputIterator, _InputIterator)
template<class _InputIterator,
class _Alloc,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
forward_list(_InputIterator, _InputIterator, _Alloc)
typedef typename base::__link_pointer __link_pointer;
public:
- typedef _Tp value_type;
- typedef _Alloc allocator_type;
+ typedef _Tp value_type;
+ typedef _Alloc allocator_type;
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
"Invalid allocator::value_type");
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef typename base::pointer pointer;
- typedef typename base::const_pointer const_pointer;
- typedef typename base::size_type size_type;
- typedef typename base::difference_type difference_type;
- typedef typename base::iterator iterator;
- typedef typename base::const_iterator const_iterator;
- typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
- typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename base::pointer pointer;
+ typedef typename base::const_pointer const_pointer;
+ typedef typename __allocator_traits<allocator_type>::size_type size_type;
+ typedef typename base::difference_type difference_type;
+ typedef typename base::iterator iterator;
+ typedef typename base::const_iterator const_iterator;
+ typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
+ typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
#if _LIBCPP_STD_VER > 17
- typedef size_type __remove_return_type;
+ typedef size_type __remove_return_type;
#else
- typedef void __remove_return_type;
+ typedef void __remove_return_type;
#endif
_LIBCPP_INLINE_VISIBILITY
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator,
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
list(_InputIterator, _InputIterator)
template<class _InputIterator,
class _Alloc,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
list(_InputIterator, _InputIterator, _Alloc)
pair<const_iterator,const_iterator> equal_range(const K& x) const; // C++14
};
+template <class InputIterator,
+ class Compare = less<iter_key_t<InputIterator>>,
+ class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
+ -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>; // C++17
+
+template<class Key, class T, class Compare = less<Key>,
+ class Allocator = allocator<pair<const Key, T>>>
+map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
+ -> map<Key, T, Compare, Allocator>; // C++17
+
+template <class InputIterator, class Allocator>
+map(InputIterator, InputIterator, Allocator)
+ -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>,
+ Allocator>; // C++17
+
+template<class Key, class T, class Allocator>
+map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; // C++17
+
template <class Key, class T, class Compare, class Allocator>
bool
operator==(const map<Key, T, Compare, Allocator>& x,
pair<const_iterator,const_iterator> equal_range(const K& x) const; // C++14
};
+template <class InputIterator,
+ class Compare = less<iter_key_t<InputIterator>>,
+ class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
+ -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>; // C++17
+
+template<class Key, class T, class Compare = less<Key>,
+ class Allocator = allocator<pair<const Key, T>>>
+multimap(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
+ -> multimap<Key, T, Compare, Allocator>; // C++17
+
+template <class InputIterator, class Allocator>
+multimap(InputIterator, InputIterator, Allocator)
+ -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ less<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class Key, class T, class Allocator>
+multimap(initializer_list<pair<const Key, T>>, Allocator)
+ -> multimap<Key, T, less<Key>, Allocator>; // C++17
+
template <class Key, class T, class Compare, class Allocator>
bool
operator==(const multimap<Key, T, Compare, Allocator>& x,
#include <__config>
#include <__debug>
#include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
#include <__node_handle>
#include <__tree>
#include <__utility/forward.h>
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>,
class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<!__is_allocator<_Compare>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
-> map<remove_const_t<_Key>, _Tp, _Compare, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
map(_InputIterator, _InputIterator, _Allocator)
-> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>,
class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<!__is_allocator<_Compare>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
-> multimap<remove_const_t<_Key>, _Tp, _Compare, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
multimap(_InputIterator, _InputIterator, _Allocator)
-> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
priority_queue(InputIterator, InputIterator, Allocator)
-> priority_queue<iter-value-type<InputIterator>,
vector<iter-value-type<InputIterator>, Allocator>,
- less<iter-value-type<InputIterator>>>;
+ less<iter-value-type<InputIterator>>>; // C++17
template<class InputIterator, class Compare, class Allocator>
priority_queue(InputIterator, InputIterator, Compare, Allocator)
-> priority_queue<iter-value-type<InputIterator>,
- vector<iter-value-type<InputIterator>, Allocator>, Compare>;
+ vector<iter-value-type<InputIterator>, Allocator>, Compare>; // C++17
template<class InputIterator, class Compare, class Container, class Allocator>
priority_queue(InputIterator, InputIterator, Compare, Container, Allocator)
- -> priority_queue<typename Container::value_type, Container, Compare>;
+ -> priority_queue<typename Container::value_type, Container, Compare>; // C++17
template <class T, class Container, class Compare>
void swap(priority_queue<T, Container, Compare>& x,
pair<const_iterator,const_iterator> equal_range(const K& x) const; // C++14
};
+template <class InputIterator,
+ class Compare = less<typename iterator_traits<InputIterator>::value_type>,
+ class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+set(InputIterator, InputIterator,
+ Compare = Compare(), Allocator = Allocator())
+ -> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>; // C++17
+
+template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
+set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
+ -> set<Key, Compare, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+set(InputIterator, InputIterator, Allocator)
+ -> set<typename iterator_traits<InputIterator>::value_type,
+ less<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17
+
+template<class Key, class Allocator>
+set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>; // C++17
+
template <class Key, class Compare, class Allocator>
bool
operator==(const set<Key, Compare, Allocator>& x,
pair<const_iterator,const_iterator> equal_range(const K& x) const; // C++14
};
+template <class InputIterator,
+ class Compare = less<typename iterator_traits<InputIterator>::value_type>,
+ class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+multiset(InputIterator, InputIterator,
+ Compare = Compare(), Allocator = Allocator())
+ -> multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>; // C++17
+
+template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
+multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
+ -> multiset<Key, Compare, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+multiset(InputIterator, InputIterator, Allocator)
+ -> multiset<typename iterator_traits<InputIterator>::value_type,
+ less<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17
+
+template<class Key, class Allocator>
+multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>; // C++17
+
template <class Key, class Compare, class Allocator>
bool
operator==(const multiset<Key, Compare, Allocator>& x,
#include <__config>
#include <__debug>
#include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
#include <__node_handle>
#include <__tree>
#include <__utility/forward.h>
// types:
typedef _Key key_type;
typedef key_type value_type;
- typedef _Compare key_compare;
+ typedef __identity_t<_Compare> key_compare;
typedef key_compare value_compare;
typedef __identity_t<_Allocator> allocator_type;
typedef value_type& reference;
private:
typedef __tree<value_type, value_compare, allocator_type> __base;
typedef allocator_traits<allocator_type> __alloc_traits;
- typedef typename __base::__node_holder __node_holder;
__base __tree_;
template<class _InputIterator,
class _Compare = less<__iter_value_type<_InputIterator>>,
class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>,
class = enable_if_t<!__is_allocator<_Compare>::value, void>>
set(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
template<class _Key, class _Compare = less<_Key>,
class _Allocator = allocator<_Key>,
- class = enable_if_t<__is_allocator<_Allocator>::value, void>,
- class = enable_if_t<!__is_allocator<_Compare>::value, void>>
+ class = enable_if_t<!__is_allocator<_Compare>::value, void>,
+ class = enable_if_t<__is_allocator<_Allocator>::value, void>>
set(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator())
-> set<_Key, _Compare, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
set(_InputIterator, _InputIterator, _Allocator)
-> set<__iter_value_type<_InputIterator>,
// types:
typedef _Key key_type;
typedef key_type value_type;
- typedef _Compare key_compare;
+ typedef __identity_t<_Compare> key_compare;
typedef key_compare value_compare;
typedef __identity_t<_Allocator> allocator_type;
typedef value_type& reference;
private:
typedef __tree<value_type, value_compare, allocator_type> __base;
typedef allocator_traits<allocator_type> __alloc_traits;
- typedef typename __base::__node_holder __node_holder;
__base __tree_;
template<class _InputIterator,
class _Compare = less<__iter_value_type<_InputIterator>>,
class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>,
class = enable_if_t<!__is_allocator<_Compare>::value, void>>
multiset(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
-> multiset<_Key, _Compare, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
class = enable_if_t<__is_allocator<_Allocator>::value, void>>
multiset(_InputIterator, _InputIterator, _Allocator)
-> multiset<__iter_value_type<_InputIterator>,
void reserve(size_type n);
};
+template<class InputIterator,
+ class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
+ class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+unordered_map(InputIterator, InputIterator, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_map<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred,
+ Allocator>; // C++17
+
+template<class Key, class T, class Hash = hash<Key>,
+ class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_map<Key, T, Hash, Pred, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_map(InputIterator, InputIterator, Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
+ -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
+ equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class Key, class T, typename Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator)
+ -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17
+
+template<class Key, class T, typename Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, Allocator)
+ -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17
+
+template<class Key, class T, class Hash, class Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Hash, Allocator)
+ -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>; // C++17
+
template <class Key, class T, class Hash, class Pred, class Alloc>
void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
unordered_map<Key, T, Hash, Pred, Alloc>& y)
void reserve(size_type n);
};
+template<class InputIterator,
+ class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
+ class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_multimap<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred,
+ Allocator>; // C++17
+
+template<class Key, class T, class Hash = hash<Key>,
+ class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_multimap<Key, T, Hash, Pred, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator)
+ -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_multimap(InputIterator, InputIterator, Allocator)
+ -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+ hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
+ -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
+ equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17
+
+template<class Key, class T, typename Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator)
+ -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17
+
+template<class Key, class T, typename Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, Allocator)
+ -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17
+
+template<class Key, class T, class Hash, class Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type, Hash,
+ Allocator)
+ -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>; // C++17
+
template <class Key, class T, class Hash, class Pred, class Alloc>
void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
#include <__config>
#include <__debug>
#include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
#include <__hash_table>
#include <__node_handle>
#include <__utility/forward.h>
class _Hash = hash<__iter_key_type<_InputIterator>>,
class _Pred = equal_to<__iter_key_type<_InputIterator>>,
class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<!__is_allocator<_Pred>::value>,
-> unordered_map<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
-> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_map(_InputIterator, _InputIterator, _Allocator)
-> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
template<class _InputIterator, class _Hash, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
class _Hash = hash<__iter_key_type<_InputIterator>>,
class _Pred = equal_to<__iter_key_type<_InputIterator>>,
class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<!__is_allocator<_Pred>::value>,
-> unordered_multimap<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
-> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_multimap(_InputIterator, _InputIterator, _Allocator)
-> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
template<class _InputIterator, class _Hash, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
void reserve(size_type n);
};
+template<class InputIterator,
+ class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
+ class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
+ class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+unordered_set(InputIterator, InputIterator, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_set<typename iterator_traits<InputIterator>::value_type,
+ Hash, Pred, Allocator>; // C++17
+
+template<class T, class Hash = hash<T>,
+ class Pred = equal_to<T>, class Allocator = allocator<T>>
+unordered_set(initializer_list<T>, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_set<T, Hash, Pred, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
+ -> unordered_set<typename iterator_traits<InputIterator>::value_type,
+ hash<typename iterator_traits<InputIterator>::value_type>,
+ equal_to<typename iterator_traits<InputIterator>::value_type>,
+ Allocator>; // C++17
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_set(InputIterator, InputIterator, typename see below::size_type,
+ Hash, Allocator)
+ -> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash,
+ equal_to<typename iterator_traits<InputIterator>::value_type>,
+ Allocator>; // C++17
+
+template<class T, class Allocator>
+unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
+ -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; // C++17
+
+template<class T, class Hash, class Allocator>
+unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
+ -> unordered_set<T, Hash, equal_to<T>, Allocator>; // C++17
+
template <class Value, class Hash, class Pred, class Alloc>
void swap(unordered_set<Value, Hash, Pred, Alloc>& x,
unordered_set<Value, Hash, Pred, Alloc>& y)
void reserve(size_type n);
};
+template<class InputIterator,
+ class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
+ class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
+ class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+unordered_multiset(InputIterator, InputIterator, see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
+ Hash, Pred, Allocator>; // C++17
+
+template<class T, class Hash = hash<T>,
+ class Pred = equal_to<T>, class Allocator = allocator<T>>
+unordered_multiset(initializer_list<T>, typename see below::size_type = see below,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> unordered_multiset<T, Hash, Pred, Allocator>; // C++17
+
+template<class InputIterator, class Allocator>
+unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator)
+ -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
+ hash<typename iterator_traits<InputIterator>::value_type>,
+ equal_to<typename iterator_traits<InputIterator>::value_type>,
+ Allocator>; // C++17
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_multiset(InputIterator, InputIterator, typename see below::size_type,
+ Hash, Allocator)
+ -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash,
+ equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17
+
+template<class T, class Allocator>
+unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator)
+ -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; // C++17
+
+template<class T, class Hash, class Allocator>
+unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator)
+ -> unordered_multiset<T, Hash, equal_to<T>, Allocator>; // C++17
+
template <class Value, class Hash, class Pred, class Alloc>
void swap(unordered_multiset<Value, Hash, Pred, Alloc>& x,
unordered_multiset<Value, Hash, Pred, Alloc>& y)
class _Hash = hash<__iter_value_type<_InputIterator>>,
class _Pred = equal_to<__iter_value_type<_InputIterator>>,
class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<!__is_allocator<_Pred>::value>,
-> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_set(_InputIterator, _InputIterator,
typename allocator_traits<_Allocator>::size_type, _Allocator)
_Allocator>;
template<class _InputIterator, class _Hash, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
class _Hash = hash<__iter_value_type<_InputIterator>>,
class _Pred = equal_to<__iter_value_type<_InputIterator>>,
class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<!__is_allocator<_Pred>::value>,
-> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
template<class _InputIterator, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
-> unordered_multiset<__iter_value_type<_InputIterator>,
_Allocator>;
template<class _InputIterator, class _Hash, class _Allocator,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<!__is_allocator<_Hash>::value>,
class = enable_if_t<!is_integral<_Hash>::value>,
class = enable_if_t<__is_allocator<_Allocator>::value>>
template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
vector(InputIterator, InputIterator, Allocator = Allocator())
- -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
+ -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17
template <class Allocator> struct hash<std::vector<bool, Allocator>>;
#include <__bit_reference>
#include <__debug>
#include <__functional_base>
+#include <__iterator/iterator_traits.h>
#include <__iterator/wrap_iter.h>
#include <__split_buffer>
#include <__utility/forward.h>
: private __vector_base<_Tp, _Allocator>
{
private:
- typedef __vector_base<_Tp, _Allocator> __base;
- typedef allocator<_Tp> __default_allocator_type;
+ typedef __vector_base<_Tp, _Allocator> __base;
+ typedef allocator<_Tp> __default_allocator_type;
public:
- typedef vector __self;
- typedef _Tp value_type;
- typedef _Allocator allocator_type;
- typedef allocator_traits<allocator_type> __alloc_traits;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef typename __alloc_traits::size_type size_type;
- typedef typename __alloc_traits::difference_type difference_type;
- typedef typename __alloc_traits::pointer pointer;
- typedef typename __alloc_traits::const_pointer const_pointer;
- typedef __wrap_iter<pointer> iterator;
- typedef __wrap_iter<const_pointer> const_iterator;
- typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
+ typedef vector __self;
+ typedef _Tp value_type;
+ typedef _Allocator allocator_type;
+ typedef allocator_traits<allocator_type> __alloc_traits;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename __allocator_traits<allocator_type>::size_type size_type;
+ typedef typename __alloc_traits::difference_type difference_type;
+ typedef typename __alloc_traits::pointer pointer;
+ typedef typename __alloc_traits::const_pointer const_pointer;
+ typedef __wrap_iter<pointer> iterator;
+ typedef __wrap_iter<const_pointer> const_iterator;
+ typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
#if _LIBCPP_STD_VER >= 17
template<class _InputIterator,
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
vector(_InputIterator, _InputIterator)
template<class _InputIterator,
class _Alloc,
+ class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
class = enable_if_t<__is_allocator<_Alloc>::value>
>
vector(_InputIterator, _InputIterator, _Alloc)
#include <map>
#include <type_traits>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
using P = std::pair<int, long>;
ASSERT_SAME_TYPE(decltype(m2), std::map<int, int>);
}
+ AssociativeContainerDeductionGuidesSfinaeAway<std::map, std::map<int, long>>();
+
return 0;
}
#include <map>
#include <type_traits>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
using P = std::pair<int, long>;
ASSERT_SAME_TYPE(decltype(m2), std::multimap<int, int>);
}
+ AssociativeContainerDeductionGuidesSfinaeAway<std::multimap, std::multimap<int, long>>();
+
return 0;
}
#include <set>
#include <type_traits>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
struct NotAnAllocator {
assert(s.size() == 2);
}
+ AssociativeContainerDeductionGuidesSfinaeAway<std::multiset, std::multiset<int>>();
+
return 0;
}
#include <set>
#include <type_traits>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
struct NotAnAllocator {
assert(s.size() == 2);
}
+ AssociativeContainerDeductionGuidesSfinaeAway<std::set, std::set<int>>();
+
return 0;
}
#include <cstddef>
#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ // Deduction guides should be SFINAE'd away when given:
+ // - "bad" input iterators (that is, a type not qualifying as an input
+ // iterator);
+ // - a bad allocator;
+ // - an allocator instead of a comparator;
+ // - an allocator instead of a container;
+ // - an allocator and a container that uses a different allocator.
+ {
+ using Comp = std::less<int>;
+ using Cont = std::vector<int>;
+ using Alloc = std::allocator<int>;
+ using Iter = int*;
+
+ // The only requirement in the Standard is that integral types cannot be
+ // considered input iterators, beyond that it is unspecified.
+ using BadIter = int;
+#ifdef _LIBCPP_VERSION
+ struct OutputIter {
+ using iterator_category = std::output_iterator_tag;
+ using value_type = void;
+ using difference_type = void;
+ using pointer = void;
+ using reference = void;
+
+ const OutputIter& operator*() const { return *this; }
+ const OutputIter& operator++() { return *this; }
+ OutputIter operator++(int) const { return *this; }
+ };
+#endif // _LIBCPP_VERSION
+
+ struct BadAlloc {};
+ using AllocAsComp = Alloc;
+ using AllocAsCont = Alloc;
+ using DiffAlloc = test_allocator<int>;
+
+ // (iter, iter)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter)
+ static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter>);
+ // Note: (OutputIter, OutputIter) is interpreted as (comp, cont) and fails on accessing
+ // non-existent typedefs in `OutputIter` (as if it were a container). There is no
+ // requirement to SFINAE away bad containers.
+
+ // (iter, iter, comp)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, comp)
+ static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<std::priority_queue, OutputIter, OutputIter, Comp>);
+ // Note: (iter, iter, ALLOC_as_comp) is allowed -- it just calls (iter, iter, alloc).
+
+ // (iter, iter, comp, cont)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, comp, cont)
+ static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp, Cont>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<std::priority_queue, OutputIter, OutputIter, Comp, Cont>);
+ // Cannot deduce from (iter, iter, ALLOC_as_comp, cont)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Cont>);
+ // Note: (iter, iter, comp, ALLOC_as_cont) is allowed -- it just calls (iter, iter, comp,
+ // alloc).
+
+ // (iter, iter, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Alloc>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<std::priority_queue, OutputIter, OutputIter, Alloc>);
+ // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp) instead and fails upon
+ // instantiation. There is no requirement to SFINAE away bad comparators.
+
+ // (iter, iter, comp, alloc)
+ //
+ // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Alloc>);
+ // Note: (iter, iter, comp, BAD_alloc) is interpreted as (iter, iter, comp, cont) instead
+ // and fails upon instantiation. There is no requirement to SFINAE away bad containers.
+
+ // (iter, iter, comp, cont, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, comp, cont, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp, Cont, Alloc>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<std::priority_queue, OutputIter, OutputIter, Comp, Cont, Alloc>);
+ // Cannot deduce from (iter, iter, ALLOC_as_comp, cont, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Cont, Alloc>);
+ // Cannot deduce from (iter, iter, comp, ALLOC_as_cont, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, Comp, AllocAsCont, Alloc>);
+ // Cannot deduce from (iter, iter, comp, cont, BAD_alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, Comp, Cont, BadAlloc>);
+ // Cannot deduce from (iter, iter, comp, cont, DIFFERENT_alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, Comp, Cont, DiffAlloc>);
+
+ // (comp, alloc)
+ //
+ // Cannot deduce from (ALLOC_as_comp, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Alloc>);
+ // Cannot deduce from (comp, BAD_alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Comp, BadAlloc>);
+
+ // (comp, cont, alloc)
+ //
+ // Cannot deduce from (ALLOC_as_comp, cont, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Cont, Alloc>);
+ // Cannot deduce from (comp, ALLOC_as_cont, alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Comp, AllocAsCont, Alloc>);
+ // Cannot deduce from (comp, cont, BAD_alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Comp, Cont, BadAlloc>);
+ // Cannot deduce from (comp, cont, DIFFERENT_alloc)
+ static_assert(SFINAEs_away<std::priority_queue, Comp, Cont, DiffAlloc>);
+
+ // (comp, cont)
+ //
+ // Cannot deduce from (ALLOC_as_comp, cont)
+ static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Cont>);
+ // Cannot deduce from (comp, ALLOC_as_cont)
+ static_assert(SFINAEs_away<std::priority_queue, Comp, AllocAsCont>);
+ }
+
return 0;
}
#include <iterator>
#include <cassert>
#include <cstddef>
-#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ // Deduction guides should be SFINAE'd away when given:
+ // - a "bad" allocator (that is, a type not qualifying as an allocator);
+ // - an allocator instead of a container;
+ // - an allocator and a container that uses a different allocator.
+ {
+ using Cont = std::list<int>;
+ using Alloc = std::allocator<int>;
+ using DiffAlloc = test_allocator<int>;
+
+ struct BadAlloc {};
+ using AllocAsCont = Alloc;
+
+ // (cont, alloc)
+ //
+ // Cannot deduce from (ALLOC_as_cont, alloc)
+ static_assert(SFINAEs_away<std::queue, AllocAsCont, BadAlloc>);
+ // Cannot deduce from (cont, BAD_alloc)
+ static_assert(SFINAEs_away<std::queue, Cont, BadAlloc>);
+ // Cannot deduce from (cont, DIFFERENT_alloc)
+ static_assert(SFINAEs_away<std::queue, Cont, DiffAlloc>);
+ }
+
return 0;
}
#include <cstddef>
#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ // Deduction guides should be SFINAE'd away when given:
+ // - a "bad" allocator (that is, a type not qualifying as an allocator);
+ // - an allocator instead of a container;
+ // - an allocator and a container that uses a different allocator.
+ {
+ using Cont = std::list<int>;
+ using Alloc = std::allocator<int>;
+ using DiffAlloc = test_allocator<int>;
+
+ struct BadAlloc {};
+ using AllocAsCont = Alloc;
+
+ // (cont, alloc)
+ //
+ // Cannot deduce from (ALLOC_as_cont, alloc)
+ static_assert(SFINAEs_away<std::stack, AllocAsCont, Alloc>);
+ // Cannot deduce from (cont, BAD_alloc)
+ static_assert(SFINAEs_away<std::stack, Cont, BadAlloc>);
+ // Cannot deduce from (cont, DIFFERENT_alloc)
+ static_assert(SFINAEs_away<std::stack, Cont, DiffAlloc>);
+ }
+
return 0;
}
#include <cstddef>
#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ SequenceContainerDeductionGuidesSfinaeAway<std::deque, std::deque<int>>();
+
return 0;
}
#include <cstddef>
#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ SequenceContainerDeductionGuidesSfinaeAway<std::forward_list, std::forward_list<int>>();
+
return 0;
}
#include <cstddef>
#include <climits> // INT_MAX
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ SequenceContainerDeductionGuidesSfinaeAway<std::list, std::list<int>>();
+
return 0;
}
//
#include <vector>
-#include <iterator>
#include <cassert>
#include <cstddef>
#include <climits> // INT_MAX
+#include <iterator>
+#include <type_traits>
+#include "deduction_guides_sfinae_checks.h"
#include "test_macros.h"
#include "test_iterators.h"
#include "test_allocator.h"
}
}
+ SequenceContainerDeductionGuidesSfinaeAway<std::vector, std::vector<int>>();
+
return 0;
}
#include <type_traits>
#include <unordered_map>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
using P = std::pair<int, long>;
ASSERT_SAME_TYPE(decltype(m2), std::unordered_map<int, int>);
}
+ UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_map, std::unordered_map<int, long>>();
+
return 0;
}
#include <type_traits>
#include <unordered_map>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
using P = std::pair<int, long>;
ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>);
}
+ UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, std::unordered_multimap<int, long>>();
+
return 0;
}
#include <type_traits>
#include <unordered_set>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
int main(int, char**)
assert(s.get_allocator().get_id() == 42);
}
+ UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multiset, std::unordered_multiset<int>>();
+
return 0;
}
#include <type_traits>
#include <unordered_set>
+#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
int main(int, char**)
assert(s.get_allocator().get_id() == 42);
}
+ UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_set, std::unordered_set<int>>();
+
return 0;
}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <memory>
+
+// unique_ptr
+
+// The following constructors should not be selected by class template argument
+// deduction:
+//
+// explicit unique_ptr(pointer p)
+// unique_ptr(pointer p, const D& d) noexcept
+// unique_ptr(pointer p, remove_reference_t<D>&& d) noexcept
+
+#include <memory>
+
+#include "deduction_guides_sfinae_checks.h"
+
+struct Deleter {
+ void operator()(int* p) const { delete p; }
+};
+
+int main(int, char**) {
+ // Cannot deduce from (ptr).
+ static_assert(SFINAEs_away<std::unique_ptr, int*>);
+ // Cannot deduce from (array).
+ static_assert(SFINAEs_away<std::unique_ptr, int[]>);
+ // Cannot deduce from (ptr, Deleter&&).
+ static_assert(SFINAEs_away<std::unique_ptr, int*, Deleter&&>);
+ // Cannot deduce from (array, Deleter&&).
+ static_assert(SFINAEs_away<std::unique_ptr, int[], Deleter&&>);
+ // Cannot deduce from (ptr, const Deleter&).
+ static_assert(SFINAEs_away<std::unique_ptr, int*, const Deleter&>);
+ // Cannot deduce from (array, const Deleter&).
+ static_assert(SFINAEs_away<std::unique_ptr, int[], const Deleter&>);
+
+ return 0;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H
+#define TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H
+
+#include <initializer_list>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+// `SFINAEs_away` template variable checks whether the template arguments for
+// a given template class `Instantiated` can be deduced from the given
+// constructor parameter types `CtrArgs` using CTAD.
+
+template<template<typename ...> class Instantiated, class ...CtrArgs,
+ class = decltype(Instantiated(std::declval<CtrArgs>()...))>
+std::false_type SFINAEs_away_impl(int);
+
+template<template<typename ...> class Instantiated, class ...CtrArgs>
+std::true_type SFINAEs_away_impl(...);
+
+template<template<typename ...> class Instantiated, class ...CtrArgs>
+constexpr bool SFINAEs_away =
+ decltype(SFINAEs_away_impl<Instantiated, CtrArgs...>(0))::value;
+
+// For sequence containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+// iterator);
+// - a bad allocator.
+template<template<typename ...> class Container, typename InstantiatedContainer>
+constexpr void SequenceContainerDeductionGuidesSfinaeAway() {
+ using Alloc = std::allocator<int>;
+ using Iter = int*;
+
+ struct BadAlloc {};
+ // Note: the only requirement in the Standard is that integral types cannot be
+ // considered input iterators; however, this doesn't work for sequence
+ // containers because they have constructors of the form `(size_type count,
+ // const value_type& value)`. These constructors would be used when passing
+ // two integral types and would deduce `value_type` to be an integral type.
+#ifdef _LIBCPP_VERSION
+ using OutputIter = std::insert_iterator<InstantiatedContainer>;
+#endif // _LIBCPP_VERSION
+
+ // (iter, iter)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter)
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>);
+
+ // (iter, iter, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>);
+ // Cannot deduce from (iter, iter, BAD_alloc)
+ static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>);
+
+ // (alloc)
+ //
+ // Cannot deduce from (alloc)
+ static_assert(SFINAEs_away<Container, Alloc>);
+}
+
+// For associative containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+// iterator);
+// - a bad allocator;
+// - an allocator in place of a comparator.
+
+template<template<typename ...> class Container, typename InstantiatedContainer>
+constexpr void AssociativeContainerDeductionGuidesSfinaeAway() {
+ using ValueType = typename InstantiatedContainer::value_type;
+ using Comp = std::less<int>;
+ using Alloc = std::allocator<ValueType>;
+ using Iter = ValueType*;
+ using InitList = std::initializer_list<ValueType>;
+
+ struct BadAlloc {};
+ // The only requirement in the Standard is that integral types cannot be
+ // considered input iterators, beyond that it is unspecified.
+ using BadIter = int;
+#ifdef _LIBCPP_VERSION
+ using OutputIter = std::insert_iterator<InstantiatedContainer>;
+#endif // _LIBCPP_VERSION
+ using AllocAsComp = Alloc;
+
+ // (iter, iter)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>);
+
+ // (iter, iter, comp)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, comp)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Comp>);
+
+ // (iter, iter, comp, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, comp, alloc)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp, Alloc>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<Container, OutputIter, OutputIter, Comp, Alloc>);
+ // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc)
+ static_assert(SFINAEs_away<Container, Iter, Iter, AllocAsComp, Alloc>);
+ // Cannot deduce from (iter, iter, comp, BAD_alloc)
+ static_assert(SFINAEs_away<Container, Iter, Iter, Comp, BadAlloc>);
+
+ // (iter, iter, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>);
+ // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp)
+ // instead and fails upon instantiation. There is no requirement to SFINAE
+ // away bad comparators.
+
+ // (init_list, comp, alloc)
+ //
+ // Cannot deduce from (init_list, ALLOC_as_comp, alloc)
+ static_assert(SFINAEs_away<Container, InitList, AllocAsComp, Alloc>);
+ // Cannot deduce from (init_list, comp, BAD_alloc)
+ static_assert(SFINAEs_away<Container, InitList, Comp, BadAlloc>);
+
+ // (init_list, alloc)
+ //
+ // Note: (init_list, BAD_alloc) is interpreted as (init_list, comp) instead
+ // and fails upon instantiation. There is no requirement to SFINAE away bad
+ // comparators.
+}
+
+// For unordered containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+// iterator);
+// - a bad allocator;
+// - a bad hash functor (an integral type in place of a hash);
+// - an allocator in place of a hash functor;
+// - an allocator in place of a predicate.
+template<template<typename ...> class Container, typename InstantiatedContainer>
+constexpr void UnorderedContainerDeductionGuidesSfinaeAway() {
+ using ValueType = typename InstantiatedContainer::value_type;
+ using Pred = std::equal_to<int>;
+ using Hash = std::hash<int>;
+ using Alloc = std::allocator<ValueType>;
+ using Iter = ValueType*;
+ using InitList = std::initializer_list<ValueType>;
+
+ using BadHash = int;
+ struct BadAlloc {};
+ // The only requirement in the Standard is that integral types cannot be
+ // considered input iterators, beyond that it is unspecified.
+ using BadIter = int;
+#ifdef _LIBCPP_VERSION
+ using OutputIter = std::insert_iterator<InstantiatedContainer>;
+#endif // _LIBCPP_VERSION
+ using AllocAsHash = Alloc;
+ using AllocAsPred = Alloc;
+
+ // (iter, iter)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>);
+
+ // (iter, iter, buckets)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, size_t>);
+
+ // (iter, iter, buckets, hash)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<Container, OutputIter, OutputIter, size_t, Hash>);
+ // Cannot deduce from (iter, iter, buckets, BAD_hash)
+ static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash>);
+ // Note: (iter, iter, buckets, ALLOC_as_hash) is allowed -- it just calls
+ // (iter, iter, buckets, alloc)
+
+ // (iter, iter, buckets, hash, pred)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Pred>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<Container, OutputIter, OutputIter, size_t, Hash, Pred>);
+ // Cannot deduce from (iter, iter, buckets, BAD_hash, pred)
+ static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Pred>);
+ // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred)
+ static_assert(SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Pred>);
+ // Note: (iter, iter, buckets, hash, ALLOC_as_pred) is allowed -- it just
+ // calls (iter, iter, buckets, hash, alloc)
+
+ // (iter, iter, buckets, hash, pred, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Pred, Alloc>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter,
+ size_t, Hash, Pred, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, BAD_hash, pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Pred, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Pred, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, hash, ALLOC_as_pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, Iter, Iter, size_t, Hash, AllocAsPred, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, hash, pred, BAD_alloc)
+ static_assert(
+ SFINAEs_away<Container, Iter, Iter, size_t, Hash, Pred, BadAlloc>);
+
+ // (iter, iter, buckets, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets, alloc)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Alloc>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<Container, OutputIter, OutputIter, size_t, Alloc>);
+ // Note: (iter, iter, buckets, BAD_alloc) is interpreted as (iter, iter,
+ // buckets, hash), which is valid because the only requirement for the hash
+ // parameter is that it's not integral.
+
+ // (iter, iter, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>);
+ LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>);
+ // Cannot deduce from (iter, iter, BAD_alloc)
+ static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>);
+
+ // (iter, iter, buckets, hash, alloc)
+ //
+ // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, alloc)
+ static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Alloc>);
+ LIBCPP_STATIC_ASSERT(
+ SFINAEs_away<Container, OutputIter, OutputIter, size_t, Hash, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, BAD_hash, alloc)
+ static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Alloc>);
+ // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, alloc)
+ static_assert(
+ SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Alloc>);
+ // Note: (iter, iter, buckets, hash, BAD_alloc) is interpreted as (iter, iter,
+ // buckets, hash, pred), which is valid because there are no requirements for
+ // the predicate.
+
+ // (init_list, buckets, hash)
+ //
+ // Cannot deduce from (init_list, buckets, BAD_hash)
+ static_assert(SFINAEs_away<Container, InitList, size_t, BadHash>);
+ // Note: (init_list, buckets, ALLOC_as_hash) is interpreted as (init_list,
+ // buckets, alloc), which is valid.
+
+ // (init_list, buckets, hash, pred)
+ //
+ // Cannot deduce from (init_list, buckets, BAD_hash, pred)
+ static_assert(SFINAEs_away<Container, InitList, size_t, BadHash, Pred>);
+ // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred)
+ static_assert(SFINAEs_away<Container, InitList, size_t, AllocAsHash, Pred>);
+ // Note: (init_list, buckets, hash, ALLOC_as_pred) is interpreted as
+ // (init_list, buckets, hash, alloc), which is valid.
+
+ // (init_list, buckets, hash, pred, alloc)
+ //
+ // Cannot deduce from (init_list, buckets, BAD_hash, pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, InitList, size_t, BadHash, Pred, Alloc>);
+ // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, InitList, size_t, AllocAsHash, Pred, Alloc>);
+ // Cannot deduce from (init_list, buckets, hash, ALLOC_as_pred, alloc)
+ static_assert(
+ SFINAEs_away<Container, InitList, size_t, Hash, AllocAsPred, Alloc>);
+ // Cannot deduce from (init_list, buckets, hash, pred, BAD_alloc)
+ static_assert(
+ SFINAEs_away<Container, InitList, size_t, Hash, Pred, BadAlloc>);
+
+ // (init_list, buckets, alloc)
+ //
+ // Note: (init_list, buckets, BAD_alloc) is interpreted as (init_list,
+ // buckets, hash), which is valid because the only requirement for the hash
+ // parameter is that it's not integral.
+
+ // (init_list, buckets, hash, alloc)
+ //
+ // Cannot deduce from (init_list, buckets, BAD_hash, alloc)
+ static_assert(SFINAEs_away<Container, InitList, size_t, BadHash, Alloc>);
+ // Cannot deduce from (init_list, buckets, ALLOC_as_hash, alloc)
+ static_assert(SFINAEs_away<Container, InitList, size_t, AllocAsHash, Alloc>);
+
+ // (init_list, alloc)
+ //
+ // Cannot deduce from (init_list, BAD_alloc)
+ static_assert(SFINAEs_away<Container, InitList, BadAlloc>);
+}
+
+#endif // TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H