diff mbox

Add deduction guides for C++17 (P0433R2, partial)

Message ID 20170322160034.GA29525@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely March 22, 2017, 4 p.m. UTC
This adds some of the C++17 deduction guides, all except for the
allocator-aware containers and basic_regex. I have patches adding
those guide too, but am still working on the tests (some cases I
expected to  work are ill-formed, so I'm still looking into why).

	* include/bits/shared_ptr.h (shared_ptr, weak_ptr): Add deduction
	guides for C++17.
	* include/bits/std_function.h (function): Likewise.
	* include/bits/stl_pair.h (pair): Likewise.
	* include/debug/array (__gnu_debug::array): Likewise.
	* include/std/array (array): Likewise.
	* include/std/functional (make_default_searcher)
	(make_boyer_moore_searcher, make_boyer_moore_horspool_searcher):
	Remove generator functions.
	* include/std/tuple (tuple): Add deduction guides.
	* include/std/valarray (valarray): Likewise.
	* testsuite/20_util/function_objects/searchers.cc: Adjust to use
	class template argument deduction instead of generator functions.
	* testsuite/20_util/function/cons/deduction.cc: New test.
	* testsuite/20_util/optional/cons/deduction_guide.cc: Rename to ...
	* testsuite/20_util/optional/cons/deduction.cc: ... here.
	* testsuite/20_util/pair/cons/deduction.cc: New test.
	* testsuite/20_util/shared_ptr/cons/deduction.cc: New test.
	* testsuite/20_util/tuple/cons/deduction.cc: New test.
	* testsuite/20_util/tuple/element_access/get_neg.cc: Adjust dg-error.
	* testsuite/20_util/unique_ptr/cons/deduction_neg.cc: New test.
	* testsuite/20_util/weak_ptr/cons/deduction.cc: New test.
	* testsuite/23_containers/array/cons/deduction.cc: New test.
	* testsuite/23_containers/array/cons/deduction_neg.cc: New test.
	* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
	Adjust dg-error.
	* testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
	* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
	Likewise.
	* testsuite/26_numerics/valarray/deduction.cc: New test.
	* testsuite/30_threads/lock_guard/cons/deduction.cc: New test.
	* testsuite/30_threads/scoped_lock/cons/deduction.cc: New test.
	* testsuite/30_threads/unique_lock/cons/deduction.cc: New test.

Tested powerpc64le-linux, comitted to trunk.
commit beffaa9ede39cc8b9993685caa8820c1fc55382b
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Mar 22 15:37:23 2017 +0000

    Add deduction guides for C++17 (P0433R2, partial)
    
    	* include/bits/shared_ptr.h (shared_ptr, weak_ptr): Add deduction
    	guides for C++17.
    	* include/bits/std_function.h (function): Likewise.
    	* include/bits/stl_pair.h (pair): Likewise.
    	* include/debug/array (__gnu_debug::array): Likewise.
    	* include/std/array (array): Likewise.
    	* include/std/functional (make_default_searcher)
    	(make_boyer_moore_searcher, make_boyer_moore_horspool_searcher):
    	Remove generator functions.
    	* include/std/tuple (tuple): Add deduction guides.
    	* include/std/valarray (valarray): Likewise.
    	* testsuite/20_util/function_objects/searchers.cc: Adjust to use
    	class template argument deduction instead of generator functions.
    	* testsuite/20_util/function/cons/deduction.cc: New test.
    	* testsuite/20_util/optional/cons/deduction_guide.cc: Rename to ...
    	* testsuite/20_util/optional/cons/deduction.cc: ... here.
    	* testsuite/20_util/pair/cons/deduction.cc: New test.
    	* testsuite/20_util/shared_ptr/cons/deduction.cc: New test.
    	* testsuite/20_util/tuple/cons/deduction.cc: New test.
    	* testsuite/20_util/tuple/element_access/get_neg.cc: Adjust dg-error.
    	* testsuite/20_util/unique_ptr/cons/deduction_neg.cc: New test.
    	* testsuite/20_util/weak_ptr/cons/deduction.cc: New test.
    	* testsuite/23_containers/array/cons/deduction.cc: New test.
    	* testsuite/23_containers/array/cons/deduction_neg.cc: New test.
    	* testsuite/23_containers/array/tuple_interface/get_debug_neg.cc:
    	Adjust dg-error.
    	* testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
    	* testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
    	Likewise.
    	* testsuite/26_numerics/valarray/deduction.cc: New test.
    	* testsuite/30_threads/lock_guard/cons/deduction.cc: New test.
    	* testsuite/30_threads/scoped_lock/cons/deduction.cc: New test.
    	* testsuite/30_threads/unique_lock/cons/deduction.cc: New test.
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 851f9cf..fe933ff 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -355,6 +355,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend class weak_ptr<_Tp>;
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _Tp>
+    shared_ptr(weak_ptr<_Tp>) ->  shared_ptr<_Tp>;
+  template<typename _Tp, typename _Del>
+    shared_ptr(unique_ptr<_Tp, _Del>) ->  shared_ptr<_Tp>;
+#endif
+
   // 20.7.2.2.7 shared_ptr comparisons
   template<typename _Tp, typename _Up>
     inline bool
@@ -577,6 +584,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return shared_ptr<_Tp>(*this, std::nothrow); }
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _Tp>
+    weak_ptr(shared_ptr<_Tp>) ->  weak_ptr<_Tp>;
+#endif
+
   // 20.7.2.3.6 weak_ptr specialized algorithms.
   template<typename _Tp>
     inline void
diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h
index 7d77e21..b393a94 100644
--- a/libstdc++-v3/include/bits/std_function.h
+++ b/libstdc++-v3/include/bits/std_function.h
@@ -629,6 +629,43 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Invoker_type _M_invoker;
   };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename>
+    struct __function_guide_helper
+    { };
+
+  template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
+    struct __function_guide_helper<
+      _Res (_Tp::*) (_Args...) noexcept(_Nx)
+    >
+    { using type = _Res(_Args...); };
+
+  template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
+    struct __function_guide_helper<
+      _Res (_Tp::*) (_Args...) & noexcept(_Nx)
+    >
+    { using type = _Res(_Args...); };
+
+  template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
+    struct __function_guide_helper<
+      _Res (_Tp::*) (_Args...) const noexcept(_Nx)
+    >
+    { using type = _Res(_Args...); };
+
+  template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
+    struct __function_guide_helper<
+      _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
+    >
+    { using type = _Res(_Args...); };
+
+  template<typename _Res, typename... _ArgTypes>
+    function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
+
+  template<typename _Functor, typename _Signature = typename
+	   __function_guide_helper<decltype(&_Functor::operator())>::type>
+    function(_Functor) -> function<_Signature>;
+#endif
+
   // Out-of-line member definitions.
   template<typename _Res, typename... _ArgTypes>
     function<_Res(_ArgTypes...)>::
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index e5e9f1c..66f52b3 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -425,6 +425,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>;
+#endif
+
   /// Two pairs of the same type are equal iff their members are equal.
   template<typename _T1, typename _T2>
     inline _GLIBCXX_CONSTEXPR bool
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index 3ff786a..9c27922 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -225,6 +225,13 @@  namespace __debug
       { return _AT_Type::_S_ptr(_M_elems); }
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _Tp, typename... _Up>
+    array(_Tp, _Up...)
+      -> array<std::enable_if_t<(std::is_same_v<_Tp, _Up> && ...), _Tp>,
+	       1 + sizeof...(_Up)>;
+#endif
+
   // Array comparisons.
   template<typename _Tp, std::size_t _Nm>
     inline bool
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 261f2af..1c7d6dc 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -239,6 +239,13 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       { return _AT_Type::_S_ptr(_M_elems); }
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _Tp, typename... _Up>
+    array(_Tp, _Up...)
+      -> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
+	       1 + sizeof...(_Up)>;
+#endif
+
   // Array comparisons.
   template<typename _Tp, std::size_t _Nm>
     inline bool
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index ae5bc0a..3db10ca 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1175,36 +1175,6 @@  _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
       _RAIter _M_pat_end;
     };
 
-  /// Generator function for default_searcher
-  template<typename _ForwardIterator,
-	   typename _BinaryPredicate = std::equal_to<>>
-    inline default_searcher<_ForwardIterator, _BinaryPredicate>
-    make_default_searcher(_ForwardIterator __pat_first,
-			  _ForwardIterator __pat_last,
-			  _BinaryPredicate __pred = _BinaryPredicate())
-    { return { __pat_first, __pat_last, __pred }; }
-
-  /// Generator function for boyer_moore_searcher
-  template<typename _RAIter, typename _Hash
-	     = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
-	   typename _BinaryPredicate = equal_to<>>
-    inline boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>
-    make_boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last,
-			      _Hash __hf = _Hash(),
-			      _BinaryPredicate __pred = _BinaryPredicate())
-    { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
-
-  /// Generator function for boyer_moore_horspool_searcher
-  template<typename _RAIter, typename _Hash
-	     = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
-	   typename _BinaryPredicate = equal_to<>>
-    inline boyer_moore_horspool_searcher<_RAIter, _Hash, _BinaryPredicate>
-    make_boyer_moore_horspool_searcher(_RAIter __pat_first, _RAIter __pat_last,
-				       _Hash __hf = _Hash(),
-				       _BinaryPredicate __pred
-				       = _BinaryPredicate())
-    { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
-
   template<typename _RAIter, typename _Hash, typename _BinaryPredicate>
     boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>::
     boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end,
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index f53daf1..ae495d9 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -872,6 +872,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { _Inherited::_M_swap(__in); }
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename... _UTypes>
+    tuple(_UTypes...) -> tuple<_UTypes...>;
+  template<typename _T1, typename _T2>
+    tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
+  template<typename _Alloc, typename... _UTypes>
+    tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
+  template<typename _Alloc, typename _T1, typename _T2>
+    tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
+  template<typename _Alloc, typename... _UTypes>
+    tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
+#endif
+
   // Explicit specialization, zero-element tuple.
   template<>
     class tuple<>
diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray
index ad50650..2dc6e42 100644
--- a/libstdc++-v3/include/std/valarray
+++ b/libstdc++-v3/include/std/valarray
@@ -563,6 +563,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend class _Array<_Tp>;
     };
 
+#if __cpp_deduction_guides >= 201606
+  template<typename _Tp, size_t _Nm>
+    valarray(const _Tp(&)[_Nm], size_t) -> valarray<_Tp>;
+#endif
+
   template<typename _Tp>
     inline const _Tp&
     valarray<_Tp>::operator[](size_t __i) const
diff --git a/libstdc++-v3/testsuite/20_util/function/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/function/cons/deduction.cc
new file mode 100644
index 0000000..a4346e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function/cons/deduction.cc
@@ -0,0 +1,86 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <functional>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void f0v();
+void f0vn() noexcept;
+int f0i();
+int f0in() noexcept;
+long f1l(int&);
+long f1ln(double*) noexcept;
+
+void
+test01()
+{
+  std::function func1 = f0v;
+  check_type<std::function<void()>>(func1);
+
+  std::function func2 = f0vn;
+  check_type<std::function<void()>>(func2);
+
+  std::function func3 = f0i;
+  check_type<std::function<int()>>(func3);
+
+  std::function func4 = f0in;
+  check_type<std::function<int()>>(func4);
+
+  std::function func5 = f1l;
+  check_type<std::function<long(int&)>>(func5);
+
+  std::function func6 = f1ln;
+  check_type<std::function<long(double*)>>(func6);
+
+  std::function func5a = func5;
+  check_type<std::function<long(int&)>>(func5a);
+
+  std::function func6a = func6;
+  check_type<std::function<long(double*)>>(func6a);
+}
+
+struct X {
+  int operator()(const short&, void*);
+};
+
+struct Y {
+  void operator()(int) const & noexcept;
+};
+
+void
+test02()
+{
+  X x;
+  std::function func1 = x;
+  check_type<std::function<int(const short&, void*)>>(func1);
+
+  Y y;
+  std::function func2 = y;
+  check_type<std::function<void(int)>>(func2);
+
+  std::function func3 = [&x](float) -> X& { return x; };
+  check_type<std::function<X&(float)>>(func3);
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/searchers.cc b/libstdc++-v3/testsuite/20_util/function_objects/searchers.cc
index 0506ea4..9cc1455 100644
--- a/libstdc++-v3/testsuite/20_util/function_objects/searchers.cc
+++ b/libstdc++-v3/testsuite/20_util/function_objects/searchers.cc
@@ -31,9 +31,9 @@ 
 # error "Feature-test macro for searchers has wrong value"
 #endif
 
-using std::make_default_searcher;
-using std::make_boyer_moore_searcher;
-using std::make_boyer_moore_horspool_searcher;
+using std::default_searcher;
+using std::boyer_moore_searcher;
+using std::boyer_moore_horspool_searcher;
 
 void
 test01()
@@ -50,9 +50,9 @@  test01()
   for (auto n : needles)
   {
     auto ne = n + std::strlen(n);
-    auto d = make_default_searcher(n, ne);
-    auto bm = make_boyer_moore_searcher(n, ne);
-    auto bmh = make_boyer_moore_horspool_searcher(n, ne);
+    default_searcher d(n, ne);
+    boyer_moore_searcher bm(n, ne);
+    boyer_moore_horspool_searcher bmh(n, ne);
     for (auto h : haystacks)
     {
       auto he = h + std::strlen(h);
@@ -83,9 +83,9 @@  test02()
   for (auto n : needles)
   {
     auto ne = n + std::wcslen(n);
-    auto d = make_default_searcher(n, ne);
-    auto bm = make_boyer_moore_searcher(n, ne);
-    auto bmh = make_boyer_moore_horspool_searcher(n, ne);
+    default_searcher d(n, ne);
+    boyer_moore_searcher bm(n, ne);
+    boyer_moore_horspool_searcher bmh(n, ne);
     for (auto h : haystacks)
     {
       auto he = h + std::wcslen(h);
@@ -122,9 +122,9 @@  test03()
   const char* ne = needle + std::strlen(needle);
   const char* he = haystack + std::strlen(haystack);
 
-  auto d = make_default_searcher(needle, ne, eq);
-  auto bm = make_boyer_moore_searcher(needle, ne, eq, eq);
-  auto bmh = make_boyer_moore_horspool_searcher(needle, ne, eq, eq);
+  default_searcher d(needle, ne, eq);
+  boyer_moore_searcher bm(needle, ne, eq, eq);
+  boyer_moore_horspool_searcher bmh(needle, ne, eq, eq);
 
   auto res = std::search(haystack, he, needle, ne, eq);
   auto d_res = d(haystack, he);
diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/optional/cons/deduction.cc
new file mode 100644
index 0000000..e15db0b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/cons/deduction.cc
@@ -0,0 +1,49 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+#include <optional>
+#include <type_traits>
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) {}
+};
+
+int main()
+{
+  std::optional x = 5;
+  static_assert(std::is_same_v<decltype(x), std::optional<int>>);
+  int y = 42;
+  std::optional x2 = y;
+  static_assert(std::is_same_v<decltype(x2), std::optional<int>>);
+  const int z = 666;
+  std::optional x3 = z;
+  static_assert(std::is_same_v<decltype(x3), std::optional<int>>);
+  std::optional mo = MoveOnly();
+  static_assert(std::is_same_v<decltype(mo), std::optional<MoveOnly>>);
+  mo = MoveOnly();
+
+  std::optional copy = x;
+  static_assert(std::is_same_v<decltype(copy), std::optional<int>>);
+  std::optional move = std::move(mo);
+  static_assert(std::is_same_v<decltype(move), std::optional<MoveOnly>>);
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/deduction_guide.cc b/libstdc++-v3/testsuite/20_util/optional/cons/deduction_guide.cc
deleted file mode 100644
index 59698dc..0000000
--- a/libstdc++-v3/testsuite/20_util/optional/cons/deduction_guide.cc
+++ /dev/null
@@ -1,44 +0,0 @@ 
-// { dg-options "-std=gnu++17" }
-// { dg-do compile }
-
-// Copyright (C) 2017 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-#include <optional>
-#include <type_traits>
-
-struct MoveOnly
-{
-  MoveOnly() = default;
-  MoveOnly(MoveOnly&&) {}
-  MoveOnly& operator=(MoveOnly&&) {}
-};
-
-int main()
-{
-    std::optional x = 5;
-    static_assert(std::is_same_v<decltype(x), std::optional<int>>);
-    int y = 42;
-    std::optional x2 = y;
-    static_assert(std::is_same_v<decltype(x2), std::optional<int>>);
-    const int z = 666;
-    std::optional x3 = z;
-    static_assert(std::is_same_v<decltype(x3), std::optional<int>>);
-    std::optional mo = MoveOnly();
-    static_assert(std::is_same_v<decltype(mo), std::optional<MoveOnly>>);
-    mo = MoveOnly();
-}
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/pair/cons/deduction.cc
new file mode 100644
index 0000000..c8e6fd6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/deduction.cc
@@ -0,0 +1,60 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) {}
+};
+
+void
+test01()
+{
+  std::pair x{5, 6u};
+  check_type<std::pair<int, unsigned>>(x);
+  int y = 42;
+  std::pair x2{y, 48u};
+  check_type<std::pair<int, unsigned>>(x2);
+  const int z = 666;
+  std::pair x3{z, y};
+  check_type<std::pair<int, int>>(x3);
+  std::pair x4{1, x};
+  check_type<std::pair<int, std::pair<int, unsigned>>>(x4);
+  std::pair mo{MoveOnly(), 2l};
+  check_type<std::pair<MoveOnly, long>>(mo);
+  mo = {MoveOnly(), 3l};
+
+  std::pair copy = x;
+  check_type<decltype(x)>(copy);
+  std::pair copy2{x};
+  check_type<decltype(x)>(copy2);
+  std::pair move = std::move(mo);
+  check_type<decltype(mo)>(move);
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/deduction.cc
new file mode 100644
index 0000000..ecd0780
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/deduction.cc
@@ -0,0 +1,45 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <memory>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::shared_ptr<long> s;
+  std::shared_ptr s2 = s;
+  check_type<std::shared_ptr<long>>(s2);
+
+  std::weak_ptr<long> w;
+  std::shared_ptr s3(w);
+  check_type<std::shared_ptr<long>>(s3);
+
+  struct D { void operator()(double*) { } };
+  std::unique_ptr<double, D> u;
+  std::shared_ptr s4 = std::move(u);
+  check_type<std::shared_ptr<double>>(s4);
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/deduction.cc
new file mode 100644
index 0000000..47e2488
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/deduction.cc
@@ -0,0 +1,166 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) {}
+};
+
+void
+test00()
+{
+  std::tuple x;
+  check_type<std::tuple<>>(x);
+
+  std::tuple copy = x;
+  check_type<decltype(x)>(copy);
+  std::tuple move = std::move(x);
+  check_type<decltype(x)>(move);
+}
+
+void
+test01()
+{
+  std::tuple x = 5;
+  check_type<std::tuple<int>>(x);
+  int y = 42;
+  std::tuple x2 = y;
+  check_type<std::tuple<int>>(x2);
+  const int z = 666;
+  std::tuple x3 = z;
+  check_type<std::tuple<int>>(x3);
+  std::tuple mo = MoveOnly();
+  check_type<std::tuple<MoveOnly>>(mo);
+  mo = MoveOnly();
+
+  std::tuple copy = x;
+  check_type<decltype(x)>(copy);
+  std::tuple move = std::move(mo);
+  check_type<decltype(mo)>(move);
+}
+
+void
+test02()
+{
+  std::tuple x{5, 6u};
+  check_type<std::tuple<int, unsigned>>(x);
+  int y = 42;
+  std::tuple x2{y, 48u};
+  check_type<std::tuple<int, unsigned>>(x2);
+  const int z = 666;
+  std::tuple x3{z, y};
+  check_type<std::tuple<int, int>>(x3);
+  std::tuple x4{1, x};
+  check_type<std::tuple<int, decltype(x)>>(x4);
+  std::tuple mo{MoveOnly(), 2l};
+  check_type<std::tuple<MoveOnly, long>>(mo);
+  mo = {MoveOnly(), 3l};
+
+  std::tuple copy = x;
+  check_type<decltype(x)>(copy);
+  std::tuple copy2{x};
+  check_type<decltype(x)>(copy2);
+  std::tuple move = std::move(mo);
+  check_type<decltype(mo)>(move);
+}
+
+void
+test03()
+{
+  std::tuple x{5, 6u, '7'};
+  check_type<std::tuple<int, unsigned, char>>(x);
+  int y = 42;
+  std::tuple x2{y, 48u, 54l};
+  check_type<std::tuple<int, unsigned, long>>(x2);
+  const int z = 666;
+  std::tuple x3{z, y, x};
+  check_type<std::tuple<int, int, decltype(x)>>(x3);
+  std::tuple x4{1, x, x2};
+  check_type<std::tuple<int, decltype(x), decltype(x2)>>(x4);
+  std::tuple mo{MoveOnly(), 2l};
+  check_type<std::tuple<MoveOnly, long>>(mo);
+  mo = {MoveOnly(), 3l};
+
+  std::tuple copy = x;
+  check_type<decltype(x)>(copy);
+  std::tuple copy2{x};
+  check_type<decltype(x)>(copy2);
+  std::tuple move = std::move(mo);
+  check_type<decltype(mo)>(move);
+}
+
+void
+test04()
+{
+  std::pair<int, unsigned> p;
+  std::tuple x = p;
+  check_type<std::tuple<int, unsigned>>(x);
+  int y = 42;
+  std::tuple x2{p};
+  check_type<std::tuple<int, unsigned>>(x2);
+  const int z = 666;
+  std::pair<const int, unsigned> p2;
+  std::tuple x3{p2};
+  check_type<std::tuple<const int, unsigned>>(x3);
+  std::pair<int&, const unsigned&> p3{p.first, p.second};
+  std::tuple x4{p3};
+  check_type<std::tuple<int&, const unsigned&>>(x4);
+  std::tuple mo = std::pair<MoveOnly, MoveOnly>();
+  check_type<std::tuple<MoveOnly, MoveOnly>>(mo);
+
+  std::tuple copy = x4;
+  check_type<decltype(x4)>(copy);
+  std::tuple copy2{x4};
+  check_type<decltype(x4)>(copy2);
+  std::tuple move = std::move(mo);
+  check_type<decltype(mo)>(move);
+}
+
+void
+test05()
+{
+  std::allocator<double> a;
+  std::tuple x{std::allocator_arg, a, 1};
+  check_type<std::tuple<int>>(x);
+  std::tuple x2{std::allocator_arg, a, 1, '2'};
+  check_type<std::tuple<int, char>>(x2);
+
+  std::pair<float, const short> p{};
+  std::tuple x3{std::allocator_arg, a, p};
+  check_type<std::tuple<float, const short>>(x3);
+  std::tuple x4{std::allocator_arg, a, std::move(p)};
+  check_type<std::tuple<float, const short>>(x4);
+
+  std::tuple x5{std::allocator_arg, a, x};
+  check_type<decltype(x)>(x5);
+  std::tuple x6{std::allocator_arg, a, std::move(x)};
+  check_type<decltype(x)>(x6);
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
index 0dc62a2..03835f4 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
@@ -17,7 +17,7 @@ 
 
 // { dg-options "-fno-show-column" }
 // { dg-do compile { target c++14 } }
-// { dg-error "in range" "" { target *-*-* } 1284 }
+// { dg-error "in range" "" { target *-*-* } 1297 }
 
 #include <tuple>
 
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/deduction_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/deduction_neg.cc
new file mode 100644
index 0000000..23aca62
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/deduction_neg.cc
@@ -0,0 +1,36 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <memory>
+
+void
+test01()
+{
+  std::unique_ptr<long> s;
+  std::unique_ptr s2 = std::move(s); // OK
+
+  std::unique_ptr bad{new int}; // { dg-error "class template argument deduction failed" }
+
+  struct D { void operator()(double*) { } };
+  std::unique_ptr bad2{new double, D()}; // { dg-error "class template argument deduction failed" }
+}
+
+// { dg-error "no matching function" "" { target *-*-* } 29 }
+// { dg-error "no matching function" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/cons/deduction.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/cons/deduction.cc
new file mode 100644
index 0000000..ea38417
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/cons/deduction.cc
@@ -0,0 +1,39 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <memory>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::shared_ptr<long> s;
+  std::weak_ptr w(s);
+  check_type<std::weak_ptr<long>>(w);
+
+  std::weak_ptr w2(w);
+  check_type<std::weak_ptr<long>>(w2);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/array/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/array/cons/deduction.cc
new file mode 100644
index 0000000..5ce2909
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/cons/deduction.cc
@@ -0,0 +1,46 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <array>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::array a1{ 1, 2, 3 };
+  check_type<std::array<int, 3>>(a1);
+  int y = 2;
+  const int z = 3;
+  std::array a2{ 1, y, z };
+  check_type<std::array<int, 3>>(a2);
+  std::array a3{ 'a', 'b', 'c', 'd', 'e' };
+  check_type<std::array<char, 5>>(a3);
+
+  std::array copy = a1;
+  check_type<decltype(a1)>(copy);
+  std::array move = std::move(a1);
+  check_type<decltype(a1)>(move);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/array/cons/deduction_neg.cc b/libstdc++-v3/testsuite/23_containers/array/cons/deduction_neg.cc
new file mode 100644
index 0000000..ec11b05
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/cons/deduction_neg.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <array>
+
+void
+test01()
+{
+  std::array a1{}; // { dg-error "class template argument deduction failed" }
+  std::array a2{1, 2u, 3}; // { dg-error "class template argument deduction failed" }
+}
+// { dg-error "no matching function for call" "" { target *-*-* } 26 }
+// { dg-error "no matching function for call" "" { target *-*-* } 27 }
+// { dg-error "no type named .*enable_if" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
index 03d284b..81d8b93 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
@@ -27,6 +27,6 @@  int n1 = std::get<1>(a);
 int n2 = std::get<1>(std::move(a));
 int n3 = std::get<1>(ca);
 
-// { dg-error "static assertion failed" "" { target *-*-* } 281 }
-// { dg-error "static assertion failed" "" { target *-*-* } 290 }
-// { dg-error "static assertion failed" "" { target *-*-* } 298 }
+// { dg-error "static assertion failed" "" { target *-*-* } 288 }
+// { dg-error "static assertion failed" "" { target *-*-* } 297 }
+// { dg-error "static assertion failed" "" { target *-*-* } 305 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
index 0b9ca95..8983ad7 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
@@ -27,6 +27,6 @@  int n1 = std::get<1>(a);
 int n2 = std::get<1>(std::move(a));
 int n3 = std::get<1>(ca);
 
-// { dg-error "static assertion failed" "" { target *-*-* } 302 }
-// { dg-error "static assertion failed" "" { target *-*-* } 311 }
-// { dg-error "static assertion failed" "" { target *-*-* } 319 }
+// { dg-error "static assertion failed" "" { target *-*-* } 309 }
+// { dg-error "static assertion failed" "" { target *-*-* } 318 }
+// { dg-error "static assertion failed" "" { target *-*-* } 326 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
index c6a8d00..493449a 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
@@ -22,4 +22,4 @@ 
 
 typedef std::tuple_element<1, std::array<int, 1>>::type type;
 
-// { dg-error "static assertion failed" "" { target *-*-* } 350 }
+// { dg-error "static assertion failed" "" { target *-*-* } 357 }
diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/deduction.cc b/libstdc++-v3/testsuite/26_numerics/valarray/deduction.cc
new file mode 100644
index 0000000..72d4bc0
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/valarray/deduction.cc
@@ -0,0 +1,42 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <valarray>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  int arr[4] = { 1, 2, 3, 4 };
+  std::valarray v(arr, 4);
+  check_type<std::valarray<int>>(v);
+
+  std::valarray v2 = v;
+  check_type<std::valarray<int>>(v2);
+
+  std::valarray v3 = std::move(v);
+  check_type<std::valarray<int>>(v3);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/lock_guard/cons/deduction.cc b/libstdc++-v3/testsuite/30_threads/lock_guard/cons/deduction.cc
new file mode 100644
index 0000000..b72c1a1
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/lock_guard/cons/deduction.cc
@@ -0,0 +1,44 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <mutex>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::mutex m;
+  std::lock_guard l(m);
+  check_type<std::lock_guard<std::mutex>>(l);
+
+  struct Mutex {
+    void lock() { }
+    void unlock() { }
+  } m2;
+
+  std::lock_guard l2(m2);
+  check_type<std::lock_guard<Mutex>>(l2);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc
new file mode 100644
index 0000000..399de7a
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/scoped_lock/cons/deduction.cc
@@ -0,0 +1,53 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <mutex>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::scoped_lock l0;
+  check_type<std::scoped_lock<>>(l0);
+
+  struct BasicLockable {
+    void lock() { }
+    void unlock() { }
+  } m1;
+
+  std::scoped_lock l1(m1);
+  check_type<std::scoped_lock<BasicLockable>>(l1);
+
+  struct Lockable {
+    void lock() { }
+    void unlock() { }
+    bool try_lock() { return true; }
+  } m2;
+
+  std::mutex m3;
+  std::scoped_lock l2(m2, m3);
+  check_type<std::scoped_lock<Lockable, std::mutex>>(l2);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/deduction.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/deduction.cc
new file mode 100644
index 0000000..4f36bab
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/deduction.cc
@@ -0,0 +1,44 @@ 
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++1z } }
+
+#include <mutex>
+
+template<typename T, typename U> struct require_same;
+template<typename T> struct require_same<T, T> { using type = void; };
+
+template<typename T, typename U>
+  typename require_same<T, U>::type
+  check_type(U&) { }
+
+void
+test01()
+{
+  std::mutex m;
+  std::unique_lock l(m);
+  check_type<std::unique_lock<std::mutex>>(l);
+
+  struct Mutex {
+    void lock() { }
+    void unlock() { }
+  } m2;
+
+  std::unique_lock l2(m2);
+  check_type<std::unique_lock<Mutex>>(l2);
+}