[libc++] Implement deduction guides for <set>

This is part of C++17's P0433.

Thanks to Arthur O'Dwyer for the patch.

Differential Revision: https://reviews.llvm.org/D58582

llvm-svn: 363090
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: e20865c387e09ea0ebd5add15c762cd5271ff65f
diff --git a/include/set b/include/set
index 4574f69..79e8f29 100644
--- a/include/set
+++ b/include/set
@@ -446,7 +446,7 @@
     typedef key_type                                 value_type;
     typedef _Compare                                 key_compare;
     typedef key_compare                              value_compare;
-    typedef _Allocator                               allocator_type;
+    typedef typename __identity<_Allocator>::type    allocator_type;
     typedef value_type&                              reference;
     typedef const value_type&                        const_reference;
 
@@ -840,6 +840,34 @@
 #endif
 };
 
+#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
+template<class _InputIterator,
+         class _Compare = less<typename iterator_traits<_InputIterator>::value_type>,
+         class _Allocator = allocator<typename iterator_traits<_InputIterator>::value_type>,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type,
+         class = typename enable_if<!__is_allocator<_Compare>::value, void>::type>
+set(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
+  -> set<typename iterator_traits<_InputIterator>::value_type, _Compare, _Allocator>;
+
+template<class _Key, class _Compare = less<_Key>,
+         class _Allocator = allocator<_Key>,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type,
+         class = typename enable_if<!__is_allocator<_Compare>::value, void>::type>
+set(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator())
+  -> set<_Key, _Compare, _Allocator>;
+
+template<class _InputIterator, class _Allocator,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type>
+set(_InputIterator, _InputIterator, _Allocator)
+  -> set<typename iterator_traits<_InputIterator>::value_type,
+         less<typename iterator_traits<_InputIterator>::value_type>, _Allocator>;
+
+template<class _Key, class _Allocator,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type>
+set(initializer_list<_Key>, _Allocator)
+  -> set<_Key, less<_Key>, _Allocator>;
+#endif
+
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _Key, class _Compare, class _Allocator>
@@ -938,7 +966,7 @@
     typedef key_type                                 value_type;
     typedef _Compare                                  key_compare;
     typedef key_compare                              value_compare;
-    typedef _Allocator                                allocator_type;
+    typedef typename __identity<_Allocator>::type    allocator_type;
     typedef value_type&                              reference;
     typedef const value_type&                        const_reference;
 
@@ -1332,6 +1360,34 @@
 #endif
 };
 
+#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
+template<class _InputIterator,
+         class _Compare = less<typename iterator_traits<_InputIterator>::value_type>,
+         class _Allocator = allocator<typename iterator_traits<_InputIterator>::value_type>,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type,
+         class = typename enable_if<!__is_allocator<_Compare>::value, void>::type>
+multiset(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
+  -> multiset<typename iterator_traits<_InputIterator>::value_type, _Compare, _Allocator>;
+
+template<class _Key, class _Compare = less<_Key>,
+         class _Allocator = allocator<_Key>,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type,
+         class = typename enable_if<!__is_allocator<_Compare>::value, void>::type>
+multiset(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator())
+  -> multiset<_Key, _Compare, _Allocator>;
+
+template<class _InputIterator, class _Allocator,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type>
+multiset(_InputIterator, _InputIterator, _Allocator)
+  -> multiset<typename iterator_traits<_InputIterator>::value_type,
+         less<typename iterator_traits<_InputIterator>::value_type>, _Allocator>;
+
+template<class _Key, class _Allocator,
+         class = typename enable_if<__is_allocator<_Allocator>::value, void>::type>
+multiset(initializer_list<_Key>, _Allocator)
+  -> multiset<_Key, less<_Key>, _Allocator>;
+#endif
+
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _Key, class _Compare, class _Allocator>