diff mbox

Define std::is_callable and std::is_nothrow_callable

Message ID 20160804180522.GA26160@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Aug. 4, 2016, 6:05 p.m. UTC
Two new traits for C++17, as well as identical __is__callable and
__is_nothrow_callable traits defined for C++11 mode (so I can use the
latter to add an exception specification to std::__invoke).

	* doc/xml/manual/status_cxx2017.xml: Update status table.
	* include/std/functional (__inv_unwrap): Move to <type_traits>.
	(__invoke_impl): Remove exception specifications.
	(__invoke, invoke): Add exception specifications using
	__is_nothrow_callable.
	* include/std/type_traits (__inv_unwrap): Move from <functional>.
	(__is_callable_impl, __call_is_nt, __call_is_nothrow): New helpers.
	(__is_callable, __is_nothrow_callable): New traits.
	(is_callable, is_callable_v): New C++17 traits.
	(is_nothrow_callable, is_nothrow_callable_v): Likewise.
	* testsuite/20_util/is_callable/requirements/
	explicit_instantiation.cc: New test.
	* testsuite/20_util/is_callable/requirements/
	explicit_instantiation_ext.cc: New test.
	* testsuite/20_util/is_callable/requirements/typedefs.cc: New test.
	* testsuite/20_util/is_callable/requirements/typedefs_ext.cc: New
	test.
	* testsuite/20_util/is_callable/value.cc: New test.
	* testsuite/20_util/is_callable/value_ext.cc: New test.
	* testsuite/20_util/is_nothrow_callable/requirements/
	explicit_instantiation.cc: New test.
	* testsuite/20_util/is_nothrow_callable/requirements/
	explicit_instantiation_ext.cc: New test.
	* testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc:
	New test.
	* testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc:
	New test.
	* testsuite/20_util/is_nothrow_callable/value.cc: New test.
	* testsuite/20_util/is_nothrow_callable/value_ext.cc: New test.

Tested x86_64-linux, committed to trunk.
commit 8f42033a7c8f66b5a8abd05758f176e3cb3c2933
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 4 01:48:56 2016 +0100

    Define std::is_callable and std::is_nothrow_callable
    
    	* doc/xml/manual/status_cxx2017.xml: Update status table.
    	* include/std/functional (__inv_unwrap): Move to <type_traits>.
    	(__invoke_impl): Remove exception specifications.
    	(__invoke, invoke): Add exception specifications using
    	__is_nothrow_callable.
    	* include/std/type_traits (__inv_unwrap): Move from <functional>.
    	(__is_callable_impl, __call_is_nt, __call_is_nothrow): New helpers.
    	(__is_callable, __is_nothrow_callable): New traits.
    	(is_callable, is_callable_v): New C++17 traits.
    	(is_nothrow_callable, is_nothrow_callable_v): Likewise.
    	* testsuite/20_util/is_callable/requirements/
    	explicit_instantiation.cc: New test.
    	* testsuite/20_util/is_callable/requirements/
    	explicit_instantiation_ext.cc: New test.
    	* testsuite/20_util/is_callable/requirements/typedefs.cc: New test.
    	* testsuite/20_util/is_callable/requirements/typedefs_ext.cc: New
    	test.
    	* testsuite/20_util/is_callable/value.cc: New test.
    	* testsuite/20_util/is_callable/value_ext.cc: New test.
    	* testsuite/20_util/is_nothrow_callable/requirements/
    	explicit_instantiation.cc: New test.
    	* testsuite/20_util/is_nothrow_callable/requirements/
    	explicit_instantiation_ext.cc: New test.
    	* testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc:
    	New test.
    	* testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc:
    	New test.
    	* testsuite/20_util/is_nothrow_callable/value.cc: New test.
    	* testsuite/20_util/is_nothrow_callable/value_ext.cc: New test.
diff mbox

Patch

diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
index d32399d..8391758 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml
@@ -402,14 +402,13 @@  Feature-testing recommendations for C++</link>.
     </row>
 
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry> <code>is_callable</code>, the missing INVOKE related trait</entry>
       <entry>
 	<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0077r2.html">
 	P0077R2
 	</link>
       </entry>
-      <entry align="center"> No </entry>
+      <entry align="center"> 7 </entry>
       <entry><code> __cpp_lib_is_callable >= 201603 </code></entry>
     </row>
 
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index d635ef5..843dc83 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -184,18 +184,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : _Weak_result_type_impl<typename remove_cv<_Functor>::type>
     { };
 
-  template<typename _Tp, typename _Up = typename decay<_Tp>::type>
-    struct __inv_unwrap
-    {
-      using type = _Tp;
-    };
-
-  template<typename _Tp, typename _Up>
-    struct __inv_unwrap<_Tp, reference_wrapper<_Up>>
-    {
-      using type = _Up&;
-    };
-
   // Used by __invoke_impl instead of std::forward<_Tp> so that a
   // reference_wrapper is converted to an lvalue-reference.
   template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type>
@@ -206,23 +194,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res, typename _Fn, typename... _Args>
     inline _Res
     __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
-    noexcept(noexcept(std::forward<_Fn>(__f)(std::forward<_Args>(__args)...)))
     { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
 
   template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
     inline _Res
     __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
 		  _Args&&... __args)
-    noexcept(noexcept(
-	  (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...)))
     { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); }
 
   template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
     inline _Res
     __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
 		  _Args&&... __args)
-    noexcept(noexcept(
-	  ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...)))
     {
       return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
     }
@@ -230,19 +213,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res, typename _MemPtr, typename _Tp>
     inline _Res
     __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t)
-    noexcept(noexcept(__invfwd<_Tp>(__t).*__f))
     { return __invfwd<_Tp>(__t).*__f; }
 
   template<typename _Res, typename _MemPtr, typename _Tp>
     inline _Res
     __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t)
-    noexcept(noexcept((*std::forward<_Tp>(__t)).*__f))
     { return (*std::forward<_Tp>(__t)).*__f; }
 
   /// Invoke a callable object.
   template<typename _Callable, typename... _Args>
     inline typename result_of<_Callable&&(_Args&&...)>::type
     __invoke(_Callable&& __fn, _Args&&... __args)
+    noexcept(__is_nothrow_callable<_Callable(_Args...)>::value)
     {
       using __result_of = result_of<_Callable&&(_Args&&...)>;
       using __type = typename __result_of::type;
@@ -258,6 +240,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Callable, typename... _Args>
     inline result_of_t<_Callable&&(_Args&&...)>
     invoke(_Callable&& __fn, _Args&&... __args)
+    noexcept(is_nothrow_callable_v<_Callable(_Args...)>)
     {
       return std::__invoke(std::forward<_Callable>(__fn),
 			   std::forward<_Args>(__args)...);
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 693952a..baa4d1f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -176,11 +176,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename... _Bn>
     constexpr bool conjunction_v
     = conjunction<_Bn...>::value;
-  
+
   template<typename... _Bn>
     constexpr bool disjunction_v
     = disjunction<_Bn...>::value;
-  
+
   template<typename _Pp>
     constexpr bool negation_v
     = negation<_Pp>::value;
@@ -2762,6 +2762,121 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       is_nothrow_swappable_with<_Tp, _Up>::value;
 #endif // __cplusplus >= 201402L
 
+#endif// c++1z or gnu++11
+
+  // __is_callable (std::is_callable for C++11)
+
+  template<typename _Result, typename _Ret, typename = __void_t<>>
+    struct __is_callable_impl : false_type { };
+
+  template<typename _Result, typename _Ret>
+    struct __is_callable_impl<_Result, _Ret, __void_t<typename _Result::type>>
+    : __or_<is_void<_Ret>, is_convertible<typename _Result::type, _Ret>>::type
+    { };
+
+  template<typename, typename _Ret = void>
+    struct __is_callable; // not defined
+
+  template<typename _Fn, typename... _ArgTypes, typename _Ret>
+    struct __is_callable<_Fn(_ArgTypes...), _Ret>
+    : __is_callable_impl<result_of<_Fn(_ArgTypes...)>, _Ret>::type
+    { };
+
+  // Used by __invoke and __is_nothrow_callable to unwrap a reference_wrapper.
+  template<typename _Tp, typename _Up = typename decay<_Tp>::type>
+    struct __inv_unwrap
+    {
+      using type = _Tp;
+    };
+
+  template<typename _Tp, typename _Up>
+    struct __inv_unwrap<_Tp, reference_wrapper<_Up>>
+    {
+      using type = _Up&;
+    };
+
+  template<typename _Fn, typename _Tp, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_memfun_ref)
+    {
+      using _Up = typename __inv_unwrap<_Tp>::type;
+      return noexcept((std::declval<_Up>().*std::declval<_Fn>())(
+	    std::declval<_Args>()...));
+    }
+
+  template<typename _Fn, typename _Tp, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_memfun_deref)
+    {
+      return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())(
+	    std::declval<_Args>()...));
+    }
+
+  template<typename _Fn, typename _Tp>
+    constexpr bool __call_is_nt(__invoke_memobj_ref)
+    {
+      using _Up = typename __inv_unwrap<_Tp>::type;
+      return noexcept(std::declval<_Up>().*std::declval<_Fn>());
+    }
+
+  template<typename _Fn, typename _Tp>
+    constexpr bool __call_is_nt(__invoke_memobj_deref)
+    {
+      return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>());
+    }
+
+  template<typename _Fn, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_other)
+    {
+      return noexcept(std::declval<_Fn>()(std::declval<_Args>()...));
+    }
+
+  template<typename _ResultOf, typename _Fn, typename... _Args>
+    struct __call_is_nothrow
+    : __bool_constant<
+      std::__call_is_nt<_Fn, _Args...>(typename _ResultOf::__invoke_type{})>
+    { };
+
+  // __is_nothrow_callable (std::is_nothrow_callable for C++11)
+
+  template<typename, typename _Ret = void>
+    struct __is_nothrow_callable; // not defined
+
+  template<typename _Fn, typename... _Args, typename _Ret>
+    struct __is_nothrow_callable<_Fn(_Args...), _Ret>
+    : __and_<__is_callable<_Fn(_Args...), _Ret>,
+             __call_is_nothrow<result_of<_Fn(_Args...)>, _Fn, _Args...>>::type
+    { };
+
+#if __cplusplus > 201402L
+# define __cpp_lib_is_callable 201603
+
+  /// std::is_callable
+  template<typename, typename _Ret = void>
+    struct is_callable; // not defined
+
+  template<typename _Fn, typename... _ArgTypes, typename _Ret>
+    struct is_callable<_Fn(_ArgTypes...), _Ret>
+    : __is_callable<_Fn(_ArgTypes...), _Ret>::type
+    { };
+
+  /// std::is_nothrow_callable
+  template<typename, typename _Ret = void>
+    struct is_nothrow_callable; // not defined
+
+  template<typename _Fn, typename... _ArgTypes, typename _Ret>
+    struct is_nothrow_callable<_Fn(_ArgTypes...), _Ret>
+    : __is_nothrow_callable<_Fn(_ArgTypes...), _Ret>::type
+    { };
+
+  /// std::is_callable_v
+  template<typename T, typename _Ret = void>
+    constexpr bool is_callable_v = is_callable<T, _Ret>::value;
+
+  /// std::is_nothrow_callable_v
+  template<typename T, typename _Ret = void>
+    constexpr bool is_nothrow_callable_v = is_nothrow_callable<T, _Ret>::value;
+#endif // C++17
+
+
 #if __cplusplus > 201402L
 # define __cpp_lib_type_trait_variable_templates 201510L
 template <typename _Tp>
@@ -2915,7 +3030,6 @@  template <typename _Base, typename _Derived>
 template <typename _From, typename _To>
   constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
 #endif // C++17
-#endif
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..0ce5bfe
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation.cc
@@ -0,0 +1,29 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+namespace std
+{
+  struct test_type { };
+  template struct is_callable<test_type(), int>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation_ext.cc b/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation_ext.cc
new file mode 100644
index 0000000..a3d3f49
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation_ext.cc
@@ -0,0 +1,28 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+namespace std
+{
+  struct test_type { };
+  template struct __is_callable<test_type(), int>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs.cc
new file mode 100644
index 0000000..9f21dfb
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs.cc
@@ -0,0 +1,30 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::is_callable<int(), void>       test_type;
+  static_assert( std::is_base_of_v<std::false_type, test_type> );
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs_ext.cc b/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs_ext.cc
new file mode 100644
index 0000000..e582be0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs_ext.cc
@@ -0,0 +1,29 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::__is_callable<int(), void>     test_type;
+  static_assert( std::is_base_of<std::false_type, test_type>::value, "" );
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/value.cc b/libstdc++-v3/testsuite/20_util/is_callable/value.cc
new file mode 100644
index 0000000..aafd55f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/value.cc
@@ -0,0 +1,191 @@ 
+// Copyright (C) 2016 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 <type_traits>
+
+#ifndef IS_CALLABLE_DEFINED
+template<typename T, typename R = void>
+  constexpr bool is_callable()
+  {
+    static_assert(std::is_callable<T, R>::value == std::is_callable_v<T, R>);
+    return std::is_callable_v<T, R>;
+  }
+#endif
+
+void test01()
+{
+  using func_type_v0 = void(*)();
+
+  static_assert(   is_callable< func_type_v0() >(),	    "");
+  static_assert(   is_callable< func_type_v0(), void  >(),  "");
+  static_assert( ! is_callable< func_type_v0(), void* >(),  "");
+  static_assert( ! is_callable< func_type_v0(), int   >(),  "");
+
+  static_assert( ! is_callable< func_type_v0(int) >(),	      "");
+  static_assert( ! is_callable< func_type_v0(int), void  >(), "");
+  static_assert( ! is_callable< func_type_v0(int), void* >(), "");
+  static_assert( ! is_callable< func_type_v0(int), int   >(), "");
+
+  using func_type_i0 = int(*)();
+
+  static_assert(   is_callable< func_type_i0() >(),	  "");
+  static_assert(   is_callable< func_type_i0(), void >(), "");
+  static_assert(   is_callable< func_type_i0(), int  >(), "");
+  static_assert( ! is_callable< func_type_i0(), int& >(), "");
+  static_assert(   is_callable< func_type_i0(), long >(), "");
+
+  static_assert( ! is_callable< func_type_i0(int) >(),	     "");
+  static_assert( ! is_callable< func_type_i0(int), void >(), "");
+  static_assert( ! is_callable< func_type_i0(int), int  >(), "");
+  static_assert( ! is_callable< func_type_i0(int), int& >(), "");
+  static_assert( ! is_callable< func_type_i0(int), long >(), "");
+
+  using func_type_l0 = int&(*)();
+
+  static_assert(   is_callable< func_type_l0() >(),	    "");
+  static_assert(   is_callable< func_type_l0(), void >(),   "");
+  static_assert(   is_callable< func_type_l0(), int >(),    "");
+  static_assert(   is_callable< func_type_l0(), int& >(),   "");
+  static_assert( ! is_callable< func_type_l0(), int&& >(),  "");
+  static_assert(   is_callable< func_type_l0(), long >(),   "");
+  static_assert( ! is_callable< func_type_l0(), long& >(),  "");
+
+  static_assert( ! is_callable< func_type_l0(int) >(),	      "");
+  static_assert( ! is_callable< func_type_l0(int), void >(),  "");
+  static_assert( ! is_callable< func_type_l0(int), int  >(),  "");
+  static_assert( ! is_callable< func_type_l0(int), int& >(),  "");
+  static_assert( ! is_callable< func_type_l0(int), long >(),  "");
+
+  using func_type_ii = int(*)(int);
+
+  static_assert( ! is_callable< func_type_ii() >(),	  "");
+  static_assert( ! is_callable< func_type_ii(), int  >(), "");
+  static_assert( ! is_callable< func_type_ii(), int& >(), "");
+  static_assert( ! is_callable< func_type_ii(), long >(), "");
+
+  static_assert(   is_callable< func_type_ii(int) >(),	      "");
+  static_assert(   is_callable< func_type_ii(int), int  >(),  "");
+  static_assert( ! is_callable< func_type_ii(int), int& >(),  "");
+  static_assert(   is_callable< func_type_ii(int), long >(),  "");
+
+  using func_type_il = int(*)(int&);
+
+  static_assert( ! is_callable< func_type_il() >(),	  "");
+
+  static_assert( ! is_callable< func_type_il(int) >(),	      "");
+  static_assert( ! is_callable< func_type_il(int), int  >(),  "");
+  static_assert( ! is_callable< func_type_il(int), int& >(),  "");
+  static_assert( ! is_callable< func_type_il(int), long >(),  "");
+
+  static_assert(   is_callable< func_type_il(int&) >(),	      "");
+  static_assert(   is_callable< func_type_il(int&), int  >(), "");
+  static_assert( ! is_callable< func_type_il(int&), int& >(), "");
+  static_assert(   is_callable< func_type_il(int&), long >(), "");
+
+  using func_type_ir = int(*)(int&&);
+
+  static_assert( ! is_callable< func_type_ir() >(),	  "");
+
+  static_assert(   is_callable< func_type_ir(int) >(),	      "");
+  static_assert(   is_callable< func_type_ir(int), int  >(),  "");
+  static_assert( ! is_callable< func_type_ir(int), int& >(),  "");
+  static_assert(   is_callable< func_type_ir(int), long >(),  "");
+
+  static_assert( ! is_callable< func_type_ir(int&) >(),	      "");
+  static_assert( ! is_callable< func_type_ir(int&), int  >(), "");
+  static_assert( ! is_callable< func_type_ir(int&), int& >(), "");
+  static_assert( ! is_callable< func_type_ir(int&), long >(), "");
+
+  struct X { };
+
+  using mem_type_i = int X::*;
+
+  static_assert( ! is_callable< mem_type_i() >(),	  "");
+
+  static_assert( ! is_callable< mem_type_i(int) >(),	    "");
+  static_assert( ! is_callable< mem_type_i(int), int  >(),  "");
+  static_assert( ! is_callable< mem_type_i(int), int& >(),  "");
+  static_assert( ! is_callable< mem_type_i(int), long >(),  "");
+
+  static_assert( ! is_callable< mem_type_i(int&) >(),	    "");
+  static_assert( ! is_callable< mem_type_i(int&), int  >(), "");
+  static_assert( ! is_callable< mem_type_i(int&), int& >(), "");
+  static_assert( ! is_callable< mem_type_i(int&), long >(), "");
+
+  static_assert(   is_callable< mem_type_i(X&) >(),	  "");
+  static_assert(   is_callable< mem_type_i(X&), int  >(), "");
+  static_assert(   is_callable< mem_type_i(X&), int& >(), "");
+  static_assert(   is_callable< mem_type_i(X&), long >(), "");
+
+  using memfun_type_i = int (X::*)();
+
+  static_assert( ! is_callable< memfun_type_i() >(),	 "");
+
+  static_assert( ! is_callable< memfun_type_i(int) >(),	 "");
+
+  static_assert( ! is_callable< memfun_type_i(int&) >(), "");
+
+  static_assert(   is_callable< memfun_type_i(X&) >(),	      "");
+  static_assert(   is_callable< memfun_type_i(X&), int  >(),  "");
+  static_assert( ! is_callable< memfun_type_i(X&), int& >(),  "");
+  static_assert(   is_callable< memfun_type_i(X&), long >(),  "");
+  static_assert(   is_callable< memfun_type_i(X*) >(),	      "");
+
+  static_assert( ! is_callable< memfun_type_i(const X&) >(),	      "");
+  static_assert( ! is_callable< memfun_type_i(const X&), int  >(),  "");
+  static_assert( ! is_callable< memfun_type_i(X&, int) >(), "");
+
+  using memfun_type_iic = int& (X::*)(int&) const;
+
+  static_assert( ! is_callable< memfun_type_iic() >(),		      "");
+  static_assert( ! is_callable< memfun_type_iic(int)  >(),	      "");
+  static_assert( ! is_callable< memfun_type_iic(int&) >(),	      "");
+  static_assert( ! is_callable< memfun_type_iic(X&, int) >(),	      "");
+  static_assert( ! is_callable< memfun_type_iic(const X&, int) >(),  "");
+  static_assert( ! is_callable< memfun_type_iic(const X&, int&, int)  >(), "");
+
+  static_assert(   is_callable< memfun_type_iic(const X&, int&)  >(),	   "");
+  static_assert(   is_callable< memfun_type_iic(const X&, int&), int  >(), "");
+  static_assert(   is_callable< memfun_type_iic(const X&, int&), int& >(), "");
+  static_assert(   is_callable< memfun_type_iic(const X&, int&), long >(), "");
+  static_assert( ! is_callable< memfun_type_iic(const X&, int&), long& >(),"");
+  static_assert(   is_callable< memfun_type_iic(const X*, int&)  >(),	   "");
+
+  struct F {
+    int& operator()();
+    long& operator()() const;
+    short& operator()(int) &&;
+    char& operator()(int) const&;
+  private:
+    void operator()(int, int);
+  };
+  using CF = const F;
+
+  static_assert(   is_callable< F(),   int&   >(), "");
+  static_assert(   is_callable< F&(),  int&   >(), "");
+  static_assert(   is_callable< CF(),  long& >(), "");
+  static_assert(   is_callable< CF&(), long& >(), "");
+  static_assert(   is_callable< F(int),	  short& >(), "");
+  static_assert(   is_callable< F&(int),  char& >(), "");
+  static_assert(   is_callable< CF(int),  char& >(), "");
+  static_assert(   is_callable< CF&(int), char& >(), "");
+
+  static_assert( ! is_callable< F(int, int) >(), "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_callable/value_ext.cc b/libstdc++-v3/testsuite/20_util/is_callable/value_ext.cc
new file mode 100644
index 0000000..3884d6c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_callable/value_ext.cc
@@ -0,0 +1,26 @@ 
+// Copyright (C) 2016 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-do compile { target c++11 } }
+
+#include <type_traits>
+
+template<typename T, typename R = void>
+  constexpr bool is_callable() { return std::__is_callable<T, R>::value; }
+
+#define IS_CALLABLE_DEFINED
+#include "value.cc"
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..dbcdd9f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation.cc
@@ -0,0 +1,29 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+namespace std
+{
+  struct test_type { };
+  template struct is_nothrow_callable<test_type(), int>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation_ext.cc
new file mode 100644
index 0000000..9e4f74f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation_ext.cc
@@ -0,0 +1,28 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+namespace std
+{
+  struct test_type { };
+  template struct __is_nothrow_callable<test_type(), int>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc
new file mode 100644
index 0000000..395eb15
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc
@@ -0,0 +1,30 @@ 
+// { dg-options "-std=gnu++17" }
+// { dg-do compile }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::is_nothrow_callable<int(), void>       test_type;
+  static_assert( std::is_base_of_v<std::false_type, test_type> );
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc
new file mode 100644
index 0000000..23df15e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc
@@ -0,0 +1,29 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2016 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/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::__is_nothrow_callable<int(), void>     test_type;
+  static_assert( std::is_base_of<std::false_type, test_type>::value, "" );
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc
new file mode 100644
index 0000000..b24d369
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc
@@ -0,0 +1,92 @@ 
+// Copyright (C) 2016 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 <type_traits>
+
+#ifndef IS_NT_CALLABLE_DEFINED
+template<typename T, typename R = void>
+  constexpr bool is_nt_callable()
+  {
+    static_assert(std::is_nothrow_callable<T, R>::value
+                  == std::is_nothrow_callable_v<T, R>);
+    return std::is_nothrow_callable_v<T, R>;
+  }
+#endif
+
+void test01()
+{
+  using func_type = void(*)();
+  static_assert( ! is_nt_callable< func_type() >(),     "");
+
+#if __cpp_noexcept_function_type
+  using func_type_nt = void(*)() noexcept;
+  static_assert(   is_nt_callable< func_type_nt() >(),  "");
+#endif
+
+  struct X { };
+  using mem_type = int X::*;
+
+  static_assert( ! is_nt_callable< mem_type() >(),	"");
+  static_assert( ! is_nt_callable< mem_type(int) >(),   "");
+  static_assert( ! is_nt_callable< mem_type(int&) >(),	"");
+
+  static_assert(   is_nt_callable< mem_type(X&) >(),       "");
+  static_assert(   is_nt_callable< mem_type(X&), int  >(), "");
+  static_assert(   is_nt_callable< mem_type(X&), int& >(), "");
+  static_assert(   is_nt_callable< mem_type(X&), long >(), "");
+  static_assert(   is_nt_callable< mem_type(X*), int& >(), "");
+
+  using memfun_type = int (X::*)();
+
+  static_assert( ! is_nt_callable< memfun_type() >(),     "");
+  static_assert( ! is_nt_callable< memfun_type(int) >(),  "");
+  static_assert( ! is_nt_callable< memfun_type(int&) >(), "");
+  static_assert( ! is_nt_callable< memfun_type(X&) >(),   "");
+  static_assert( ! is_nt_callable< memfun_type(X*) >(),   "");
+
+#if __cpp_noexcept_function_type
+  using memfun_type_nt = int (X::*)() noexcept;
+
+  static_assert( ! is_nt_callable< memfun_type_nt() >(),	    "");
+  static_assert( ! is_nt_callable< memfun_type_nt(int) >(),  "");
+  static_assert( ! is_nt_callable< memfun_type_nt(int&) >(), "");
+  static_assert(   is_nt_callable< memfun_type_nt(X&) >(),   "");
+  static_assert(   is_nt_callable< memfun_type_nt(X*) >(),   "");
+#endif
+
+  struct F {
+    int& operator()();
+    long& operator()() const noexcept;
+    short& operator()(int) &&;
+    char& operator()(int) const& noexcept;
+  private:
+    void operator()(int, int) noexcept;
+  };
+  using CF = const F;
+
+  static_assert( ! is_nt_callable< F(),   int&   >(), "");
+  static_assert(   is_nt_callable< CF(),  long& >(),  "");
+  static_assert( ! is_nt_callable< F(int),    short& >(), "");
+  static_assert(   is_nt_callable< F&(int),   char& >(),  "");
+  static_assert(   is_nt_callable< CF(int),   char& >(),  "");
+  static_assert(   is_nt_callable< CF&(int),  char& >(),  "");
+
+  static_assert( ! is_nt_callable< F(int, int) >(), "");
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value_ext.cc
new file mode 100644
index 0000000..8d84db6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value_ext.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2016 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-do compile { target c++11 } }
+
+#include <type_traits>
+
+template<typename T, typename R = void>
+  constexpr bool is_nt_callable()
+  { return std::__is_nothrow_callable<T, R>::value; }
+
+#define IS_NT_CALLABLE_DEFINED
+#include "value.cc"