diff --git a/libcxx/docs/Status/Cxx17.rst b/libcxx/docs/Status/Cxx17.rst
--- a/libcxx/docs/Status/Cxx17.rst
+++ b/libcxx/docs/Status/Cxx17.rst
@@ -40,7 +40,6 @@
 
 .. 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.
 
 
diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv
--- a/libcxx/docs/Status/Cxx17Papers.csv
+++ b/libcxx/docs/Status/Cxx17Papers.csv
@@ -94,7 +94,7 @@
 "`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"
diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -349,6 +349,14 @@
     }
 };
 
+// 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
diff --git a/libcxx/include/deque b/libcxx/include/deque
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -129,7 +129,7 @@
 
 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);
@@ -162,6 +162,7 @@
 
 #include <__config>
 #include <__debug>
+#include <__iterator/iterator_traits.h>
 #include <__split_buffer>
 #include <__utility/forward.h>
 #include <algorithm>
@@ -1258,20 +1259,20 @@
     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;
@@ -1568,6 +1569,7 @@
 #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)
@@ -1575,13 +1577,13 @@
 
 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)
 {
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -647,7 +647,7 @@
     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;
@@ -873,6 +873,7 @@
 #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)
@@ -880,6 +881,7 @@
 
 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)
diff --git a/libcxx/include/list b/libcxx/include/list
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -845,24 +845,24 @@
     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
@@ -1144,6 +1144,7 @@
 #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)
@@ -1151,6 +1152,7 @@
 
 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)
diff --git a/libcxx/include/map b/libcxx/include/map
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -223,6 +223,25 @@
         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,
@@ -444,6 +463,26 @@
         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,
@@ -492,6 +531,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__node_handle>
 #include <__tree>
 #include <__utility/forward.h>
@@ -1501,6 +1541,7 @@
 #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())
@@ -1514,6 +1555,7 @@
   -> 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>,
@@ -2174,6 +2216,7 @@
 #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())
@@ -2187,6 +2230,7 @@
   -> 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>,
diff --git a/libcxx/include/queue b/libcxx/include/queue
--- a/libcxx/include/queue
+++ b/libcxx/include/queue
@@ -185,16 +185,16 @@
 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,
diff --git a/libcxx/include/set b/libcxx/include/set
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -183,6 +183,25 @@
         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,
@@ -389,6 +408,25 @@
         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,
@@ -436,6 +474,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__node_handle>
 #include <__tree>
 #include <__utility/forward.h>
@@ -462,7 +501,7 @@
     // 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;
@@ -474,7 +513,6 @@
 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_;
 
@@ -872,6 +910,7 @@
 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())
@@ -879,12 +918,13 @@
 
 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>,
@@ -994,7 +1034,7 @@
     // 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;
@@ -1006,7 +1046,6 @@
 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_;
 
@@ -1403,6 +1442,7 @@
 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())
@@ -1416,6 +1456,7 @@
   -> 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>,
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -216,6 +216,47 @@
     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)
@@ -404,6 +445,48 @@
     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)
@@ -434,6 +517,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__hash_table>
 #include <__node_handle>
 #include <__utility/forward.h>
@@ -1470,6 +1554,7 @@
          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>,
@@ -1490,18 +1575,21 @@
   -> 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>>
@@ -2268,6 +2356,7 @@
          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>,
@@ -2288,18 +2377,21 @@
   -> 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>>
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -182,6 +182,43 @@
     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)
@@ -359,6 +396,42 @@
     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)
@@ -803,6 +876,7 @@
          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>,
@@ -823,6 +897,7 @@
   -> 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)
@@ -832,6 +907,7 @@
                    _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>>
@@ -1468,6 +1544,7 @@
          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>,
@@ -1487,6 +1564,7 @@
   -> 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>,
@@ -1495,6 +1573,7 @@
                    _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>>
diff --git a/libcxx/include/vector b/libcxx/include/vector
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -245,7 +245,7 @@
 
 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>>;
 
@@ -275,6 +275,7 @@
 #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>
@@ -898,6 +899,7 @@
 #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)
@@ -905,6 +907,7 @@
 
 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)
diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
@@ -32,6 +32,7 @@
 #include <map>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -151,5 +152,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::map<int, int>);
     }
 
+    AssociativeContainerDeductionGuidesSfinaeAway<std::map, std::map<int, long>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
@@ -32,6 +32,7 @@
 #include <map>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -151,5 +152,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::multimap<int, int>);
     }
 
+    AssociativeContainerDeductionGuidesSfinaeAway<std::multimap, std::multimap<int, long>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
@@ -35,6 +35,7 @@
 #include <set>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 struct NotAnAllocator {
@@ -186,5 +187,7 @@
     assert(s.size() == 2);
   }
 
+  AssociativeContainerDeductionGuidesSfinaeAway<std::multiset, std::multiset<int>>();
+
   return 0;
 }
diff --git a/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
@@ -35,6 +35,7 @@
 #include <set>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 struct NotAnAllocator {
@@ -184,5 +185,7 @@
     assert(s.size() == 2);
   }
 
+  AssociativeContainerDeductionGuidesSfinaeAway<std::set, std::set<int>>();
+
   return 0;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
@@ -31,6 +31,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -239,5 +240,121 @@
         }
     }
 
+    // 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;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
@@ -21,8 +21,8 @@
 #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"
@@ -133,5 +133,27 @@
         }
     }
 
+    // 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;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
@@ -25,6 +25,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -136,5 +137,27 @@
         }
     }
 
+    // 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;
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -121,5 +122,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::deque, std::deque<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -126,5 +127,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::forward_list, std::forward_list<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -126,5 +127,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::list, std::list<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
@@ -15,11 +15,13 @@
 //
 
 #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"
@@ -139,5 +141,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::vector, std::vector<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
@@ -61,6 +61,7 @@
 #include <type_traits>
 #include <unordered_map>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -218,5 +219,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::unordered_map<int, int>);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_map, std::unordered_map<int, long>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
@@ -61,6 +61,7 @@
 #include <type_traits>
 #include <unordered_map>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -218,5 +219,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, std::unordered_multimap<int, long>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
@@ -53,6 +53,7 @@
 #include <type_traits>
 #include <unordered_set>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 int main(int, char**)
@@ -192,5 +193,7 @@
     assert(s.get_allocator().get_id() == 42);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multiset, std::unordered_multiset<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
@@ -53,6 +53,7 @@
 #include <type_traits>
 #include <unordered_set>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 int main(int, char**)
@@ -192,5 +193,7 @@
     assert(s.get_allocator().get_id() == 42);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_set, std::unordered_set<int>>();
+
     return 0;
 }
diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
diff --git a/libcxx/test/support/deduction_guides_sfinae_checks.h b/libcxx/test/support/deduction_guides_sfinae_checks.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/support/deduction_guides_sfinae_checks.h
@@ -0,0 +1,309 @@
+//===----------------------------------------------------------------------===//
+//
+// 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