diff mbox

[libstdc++] Implement the Library Fundamentals v1 variable templates for type traits

Message ID CAFk2RUbkRSH6P=JWQtJ43PO=BZfaKko+ZQjnyyL9JwJBzG43-A@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen Oct. 16, 2014, 8:04 p.m. UTC
On 16 October 2014 22:25, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> Tested on Linux-x64. The {raw,}invocable_type trait and its variable templates
> are not implemented yet.
>
>
> 2014-10-16  Ville Voutilainen  <ville.voutilainen@gmail.com>
>
>     Implement the Library Fundamentals v1 variable templates for
>     type traits.
>     * include/Makefile.am: Add the new header.
>     * include/experimental/type_traits: New.
>     * testsuite/experimental/type_traits/value.cc: Likewise.

Argh, needed to do uglification, and formatting fixes.
Also renamed the Dummy types in tests to something
a bit more descriptive. I'm not using the tr2 test types because the
test types in these tests
are amalgamations of multiple properties to keep the tests simple(r).

Comments

Jonathan Wakely Oct. 17, 2014, 12:22 p.m. UTC | #1
On 16/10/14 23:04 +0300, Ville Voutilainen wrote:
>Argh, needed to do uglification, and formatting fixes.
>Also renamed the Dummy types in tests to something
>a bit more descriptive. I'm not using the tr2 test types because the
>test types in these tests
>are amalgamations of multiple properties to keep the tests simple(r).

Thanks! Tested and committed to trunk.
diff mbox

Patch

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index e3aed84..1ee8ddc 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -643,7 +643,8 @@  experimental_headers = \
 	${experimental_srcdir}/optional \
 	${experimental_srcdir}/string_view \
 	${experimental_srcdir}/string_view.tcc \
-	${experimental_srcdir}/tuple
+	${experimental_srcdir}/tuple \
+	${experimental_srcdir}/type_traits
 
 # This is the common subset of C++ files that all three "C" header models use.
 c_base_srcdir = $(C_INCLUDE_DIR)
diff --git a/libstdc++-v3/include/experimental/type_traits b/libstdc++-v3/include/experimental/type_traits
new file mode 100644
index 0000000..8e3a058
--- /dev/null
+++ b/libstdc++-v3/include/experimental/type_traits
@@ -0,0 +1,226 @@ 
+// Variable Templates For Type Traits -*- C++ -*-
+
+// Copyright (C) 2014 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file experimental/type_traits
+ *  This is a Standard C++ Library header.
+ */
+
+//
+// N3932 Variable Templates For Type Traits (Revision 1)
+//
+
+#ifndef _GLIBCXX_EXPERIMENTAL_TYPE_TRAITS
+#define _GLIBCXX_EXPERIMENTAL_TYPE_TRAITS 1
+
+#pragma GCC system_header
+
+#if __cplusplus <= 201103L
+# include <bits/c++14_warning.h>
+#else
+
+#include <type_traits>
+
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace experimental
+{
+inline namespace fundamentals_v1
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+// See C++14 §20.10.4.1, primary type categories
+template <typename _Tp>
+  constexpr bool is_void_v = is_void<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_integral_v = is_integral<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_array_v = is_array<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_lvalue_reference_v = is_lvalue_reference<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_member_object_pointer_v =
+    is_member_object_pointer<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_member_function_pointer_v =
+    is_member_function_pointer<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_enum_v = is_enum<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_union_v = is_union<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_class_v = is_class<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_function_v = is_function<_Tp>::value;
+
+// See C++14 §20.10.4.2, composite type categories
+template <typename _Tp>
+  constexpr bool is_reference_v = is_reference<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_object_v = is_object<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_scalar_v = is_scalar<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_compound_v = is_compound<_Tp>::value;
+template <typename _Tp>
+ constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
+
+// See C++14 §20.10.4.3, type properties
+template <typename _Tp>
+  constexpr bool is_const_v = is_const<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_volatile_v = is_volatile<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivial_v = is_trivial<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_copyable_v = is_trivially_copyable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_standard_layout_v = is_standard_layout<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_pod_v = is_pod<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_literal_type_v = is_literal_type<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_empty_v = is_empty<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_abstract_v = is_abstract<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_final_v = is_final<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_signed_v = is_signed<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  constexpr bool is_constructible_v = is_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  constexpr bool is_default_constructible_v =
+    is_default_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_destructible_v = is_destructible<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  constexpr bool is_trivially_constructible_v =
+    is_trivially_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_default_constructible_v =
+    is_trivially_default_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_copy_constructible_v =
+    is_trivially_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_move_constructible_v =
+    is_trivially_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  constexpr bool is_trivially_assignable_v =
+    is_trivially_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_copy_assignable_v =
+    is_trivially_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_move_assignable_v =
+    is_trivially_move_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_trivially_destructible_v =
+    is_trivially_destructible<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  constexpr bool is_nothrow_constructible_v =
+    is_nothrow_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_default_constructible_v =
+    is_nothrow_default_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_copy_constructible_v =
+    is_nothrow_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_move_constructible_v =
+    is_nothrow_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  constexpr bool is_nothrow_assignable_v =
+    is_nothrow_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_copy_assignable_v =
+    is_nothrow_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_move_assignable_v =
+    is_nothrow_move_assignable<_Tp>::value;
+template <typename _Tp>
+  constexpr bool is_nothrow_destructible_v =
+    is_nothrow_destructible<_Tp>::value;
+template <typename _Tp>
+  constexpr bool has_virtual_destructor_v =
+    has_virtual_destructor<_Tp>::value;
+
+// See C++14 §20.10.5, type property queries
+template <typename _Tp>
+  constexpr size_t alignment_of_v = alignment_of<_Tp>::value;
+template <typename _Tp>
+  constexpr size_t rank_v = rank<_Tp>::value;
+template <typename _Tp, unsigned _Idx = 0>
+  constexpr size_t extent_v = extent<_Tp, _Idx>::value;
+
+// See C++14 §20.10.6, type relations
+template <typename _Tp, typename _Up>
+  constexpr bool is_same_v = is_same<_Tp, _Up>::value;
+template <typename _Base, typename _Derived>
+  constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value;
+template <typename _From, typename _To>
+  constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
+
+
+  // 3.3.2, Other type transformations
+  // invocation_type (still unimplemented)
+  // raw_invocation_type (still unimplemented)
+  // invocation_type_t (still unimplemented)
+  // raw_invocation_type_t (still unimplemented)
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace fundamentals_v1
+} // namespace experimental
+} // namespace std
+
+#endif // __cplusplus <= 201103L
+
+#endif // _GLIBCXX_EXPERIMENTAL_TYPE_TRAITS
diff --git a/libstdc++-v3/testsuite/experimental/type_traits/value.cc b/libstdc++-v3/testsuite/experimental/type_traits/value.cc
new file mode 100644
index 0000000..b8d9fe1
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/type_traits/value.cc
@@ -0,0 +1,324 @@ 
+// { dg-options "-std=gnu++14" }
+// { dg-do compile }
+
+// Copyright (C) 2014 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/type_traits>
+
+using namespace std;
+using namespace std::experimental;
+
+// These tests are rather simple, the front-end tests already test
+// variable templates, and the library tests for the underlying
+// traits are more elaborate. These are just simple sanity tests.
+
+static_assert(is_void_v<void> && is_void<void>::value, "");
+static_assert(!is_void_v<int> && !is_void<int>::value, "");
+
+static_assert(is_null_pointer_v<nullptr_t>
+	      && is_null_pointer<nullptr_t>::value, "");
+static_assert(!is_null_pointer_v<void*>
+	      && !is_null_pointer<void*>::value, "");
+
+static_assert(is_integral_v<int> && is_integral<int>::value, "");
+static_assert(!is_integral_v<int*> && !is_integral<int*>::value, "");
+
+static_assert(is_floating_point_v<float>
+	      && is_floating_point<float>::value, "");
+static_assert(!is_floating_point_v<int>
+	      && !is_floating_point<int>::value, "");
+
+static_assert(is_array_v<char[42]> && is_array<char[42]>::value, "");
+static_assert(!is_array_v<char*> && !is_array<char*>::value, "");
+
+static_assert(is_pointer_v<int*> && is_pointer<int*>::value, "");
+static_assert(!is_pointer_v<int> && !is_pointer<int>::value, "");
+
+static_assert(is_lvalue_reference_v<int&>
+	      && is_lvalue_reference<int&>::value, "");
+static_assert(!is_lvalue_reference_v<int>
+	      && !is_lvalue_reference<int>::value, "");
+
+static_assert(is_rvalue_reference_v<int&&>
+	      && is_rvalue_reference<int&&>::value, "");
+static_assert(!is_rvalue_reference_v<int>
+	      && !is_rvalue_reference<int>::value, "");
+
+struct EmptyFinal final {};
+
+static_assert(is_member_object_pointer_v<int (EmptyFinal::*)>
+	      && is_member_object_pointer<int (EmptyFinal::*)>::value, "");
+static_assert(!is_member_object_pointer_v<void*>
+	      && !is_member_object_pointer<void*>::value, "");
+
+static_assert(is_member_function_pointer_v<int (EmptyFinal::*)()>
+	      && is_member_function_pointer<int (EmptyFinal::*)()>::value, "");
+static_assert(!is_member_function_pointer_v<void*>
+	      && !is_member_function_pointer<void*>::value, "");
+
+enum Enum {};
+
+static_assert(is_enum_v<Enum> && is_enum<Enum>::value, "");
+static_assert(!is_enum_v<int> && !is_enum<int>::value, "");
+
+union Union;
+
+static_assert(is_union_v<Union> && is_union<Union>::value, "");
+static_assert(!is_union_v<int> && !is_union<int>::value, "");
+
+static_assert(is_class_v<EmptyFinal> && is_class<EmptyFinal>::value, "");
+static_assert(!is_class_v<int> && !is_class<int>::value, "");
+
+static_assert(is_function_v<void()> && is_function<void()>::value, "");
+static_assert(!is_function_v<void(*)()> && !is_function<void(*)()>::value, "");
+
+static_assert(is_reference_v<int&> && is_reference<int&>::value, "");
+static_assert(!is_reference_v<int> && !is_reference<int>::value, "");
+
+static_assert(is_arithmetic_v<int> && is_arithmetic<int>::value, "");
+static_assert(!is_arithmetic_v<void*> && !is_arithmetic<void*>::value, "");
+
+static_assert(is_fundamental_v<int> && is_fundamental<int>::value, "");
+static_assert(!is_fundamental_v<EmptyFinal>
+	      && !is_fundamental<EmptyFinal>::value, "");
+
+static_assert(is_object_v<int> && is_object<int>::value, "");
+static_assert(!is_object_v<int&> && !is_object<int&>::value, "");
+
+static_assert(is_scalar_v<int> && is_scalar<int>::value, "");
+static_assert(!is_scalar_v<int&> && !is_scalar<int&>::value, "");
+
+static_assert(is_compound_v<EmptyFinal>
+	      && is_compound<EmptyFinal>::value, "");
+static_assert(!is_compound_v<int> && !is_compound<int>::value, "");
+
+static_assert(is_member_pointer_v<int (EmptyFinal::*)>
+	      && is_member_pointer<int (EmptyFinal::*)>::value, "");
+static_assert(!is_member_pointer_v<void*>
+	      && !is_member_pointer<void*>::value, "");
+
+static_assert(is_const_v<const int> && is_const<const int>::value, "");
+static_assert(!is_const_v<int> && !is_const<int>::value, "");
+
+static_assert(is_volatile_v<volatile int>
+	      && is_volatile<volatile int>::value, "");
+static_assert(!is_volatile_v<int> && !is_volatile<int>::value, "");
+
+struct NType
+{
+  NType(int);
+  ~NType();
+  int i;
+private:
+  NType(const NType&);
+  NType& operator=(const NType&);
+  int i2;
+};
+
+static_assert(is_trivial_v<int> && is_trivial<int>::value, "");
+static_assert(!is_trivial_v<NType> && !is_trivial<NType>::value, "");
+
+static_assert(is_trivially_copyable_v<int>
+	      && is_trivially_copyable<int>::value, "");
+static_assert(!is_trivially_copyable_v<NType>
+	      && !is_trivially_copyable<NType>::value, "");
+
+static_assert(is_standard_layout_v<int>
+	      && is_standard_layout<int>::value, "");
+static_assert(!is_standard_layout_v<NType>
+	      && !is_standard_layout<NType>::value, "");
+
+static_assert(is_pod_v<int>
+	      && is_pod<int>::value, "");
+static_assert(!is_pod_v<NType>
+	      && !is_pod<NType>::value, "");
+
+static_assert(is_literal_type_v<int>
+	      && is_literal_type<int>::value, "");
+static_assert(!is_literal_type_v<NType>
+	      && !is_literal_type<NType>::value, "");
+
+static_assert(is_empty_v<EmptyFinal>
+	      && is_empty<EmptyFinal>::value, "");
+static_assert(!is_empty_v<NType>
+	      && !is_empty<NType>::value, "");
+
+struct Abstract {protected: virtual ~Abstract() = 0;};
+struct Poly : Abstract {virtual ~Poly();};
+
+static_assert(is_polymorphic_v<Poly>
+	      && is_polymorphic<Poly>::value, "");
+static_assert(!is_polymorphic_v<EmptyFinal>
+	      && !is_polymorphic<EmptyFinal>::value, "");
+
+
+
+static_assert(is_abstract_v<Abstract>
+	      && is_abstract<Abstract>::value, "");
+static_assert(!is_abstract_v<EmptyFinal>
+	      && !is_abstract<EmptyFinal>::value, "");
+
+static_assert(is_final_v<EmptyFinal>
+	      && is_final<EmptyFinal>::value, "");
+static_assert(!is_final_v<Abstract>
+	      && !is_final<Abstract>::value, "");
+
+static_assert(is_signed_v<int> && is_signed<int>::value, "");
+static_assert(!is_signed_v<unsigned int>
+	      && !is_signed<unsigned int>::value, "");
+
+static_assert(is_constructible_v<int, int>
+	      && is_constructible<int, int>::value, "");
+static_assert(!is_constructible_v<int, void*>
+	      && !is_constructible<int, void*>::value, "");
+
+static_assert(is_default_constructible_v<int>
+	      && is_default_constructible<int>::value, "");
+static_assert(!is_default_constructible_v<NType>
+	      && !is_default_constructible<NType>::value, "");
+
+static_assert(is_copy_constructible_v<int>
+	      && is_copy_constructible<int>::value, "");
+static_assert(!is_copy_constructible_v<NType>
+	      && !is_copy_constructible<NType>::value, "");
+
+static_assert(is_move_constructible_v<int>
+	      && is_copy_constructible<int>::value, "");
+static_assert(!is_move_constructible_v<NType>
+	      && !is_copy_constructible<NType>::value, "");
+
+static_assert(is_assignable_v<int&, int>
+	      && is_assignable<int&, int>::value, "");
+static_assert(!is_assignable_v<int, int>
+	      && !is_assignable<int, int>::value, "");
+
+static_assert(is_copy_assignable_v<int>
+	      && is_copy_assignable<int>::value, "");
+static_assert(!is_copy_assignable_v<NType>
+	      && !is_copy_assignable<NType>::value, "");
+
+static_assert(is_move_assignable_v<int>
+	      && is_move_assignable<int>::value, "");
+static_assert(!is_move_assignable_v<NType>
+	      && !is_move_assignable<NType>::value, "");
+
+static_assert(is_destructible_v<int>
+	      && is_destructible<int>::value, "");
+static_assert(!is_destructible_v<Abstract>
+	      && !is_destructible<Abstract>::value, "");
+
+static_assert(is_trivially_constructible_v<int, int>
+	      && is_trivially_constructible<int, int>::value, "");
+static_assert(!is_trivially_constructible_v<NType, NType>
+	      && !is_trivially_constructible<NType, NType>::value, "");
+
+static_assert(is_trivially_default_constructible_v<int>
+	      && is_trivially_default_constructible<int>::value, "");
+static_assert(!is_trivially_default_constructible_v<NType>
+	      && !is_trivially_default_constructible<NType>::value, "");
+
+static_assert(is_trivially_copy_constructible_v<int>
+	      && is_trivially_copy_constructible<int>::value, "");
+static_assert(!is_trivially_copy_constructible_v<NType>
+	      && !is_trivially_copy_constructible<NType>::value, "");
+
+static_assert(is_trivially_move_constructible_v<int>
+	      && is_trivially_move_constructible<int>::value, "");
+static_assert(!is_trivially_move_constructible_v<NType>
+	      && !is_trivially_move_constructible<NType>::value, "");
+
+static_assert(is_trivially_assignable_v<int&, int>
+	      && is_trivially_assignable<int&, int>::value, "");
+static_assert(!is_trivially_assignable_v<NType, NType>
+	      && !is_trivially_assignable<NType, NType>::value, "");
+
+static_assert(is_trivially_copy_assignable_v<int>
+	      && is_trivially_copy_assignable<int>::value, "");
+static_assert(!is_trivially_copy_assignable_v<NType>
+	      && !is_trivially_copy_assignable<NType>::value, "");
+
+static_assert(is_trivially_move_assignable_v<int>
+	      && is_trivially_move_assignable<int>::value, "");
+static_assert(!is_trivially_move_assignable_v<NType>
+	      && !is_trivially_move_assignable<NType>::value, "");
+
+static_assert(is_trivially_destructible_v<int>
+	      && is_trivially_destructible<int>::value, "");
+static_assert(!is_trivially_destructible_v<Abstract>
+	      && !is_trivially_destructible<Abstract>::value, "");
+
+static_assert(is_nothrow_constructible_v<int, int>
+	      && is_nothrow_constructible<int, int>::value, "");
+static_assert(!is_nothrow_constructible_v<NType, NType>
+	      && !is_nothrow_constructible<NType, NType>::value, "");
+
+static_assert(is_nothrow_default_constructible_v<int>
+	      && is_nothrow_default_constructible<int>::value, "");
+static_assert(!is_nothrow_default_constructible_v<NType>
+	      && !is_nothrow_default_constructible<NType>::value, "");
+
+static_assert(is_nothrow_copy_constructible_v<int>
+	      && is_nothrow_copy_constructible<int>::value, "");
+static_assert(!is_nothrow_copy_constructible_v<NType>
+	      && !is_nothrow_copy_constructible<NType>::value, "");
+
+static_assert(is_nothrow_move_constructible_v<int>
+	      && is_nothrow_move_constructible<int>::value, "");
+static_assert(!is_nothrow_move_constructible_v<NType>
+	      && !is_nothrow_move_constructible<NType>::value, "");
+
+static_assert(is_nothrow_assignable_v<int&, int>
+	      && is_nothrow_assignable<int&, int>::value, "");
+static_assert(!is_nothrow_assignable_v<NType, NType>
+	      && !is_nothrow_assignable<NType, NType>::value, "");
+
+static_assert(is_nothrow_copy_assignable_v<int>
+	      && is_nothrow_copy_assignable<int>::value, "");
+static_assert(!is_nothrow_copy_assignable_v<NType>
+	      && !is_nothrow_copy_assignable<NType>::value, "");
+
+static_assert(is_nothrow_move_assignable_v<int>
+	      && is_nothrow_move_assignable<int>::value, "");
+static_assert(!is_nothrow_move_assignable_v<NType>
+	      && !is_nothrow_move_assignable<NType>::value, "");
+
+static_assert(has_virtual_destructor_v<Abstract>
+	      && has_virtual_destructor<Abstract>::value, "");
+static_assert(!has_virtual_destructor_v<NType>
+	      && !has_virtual_destructor<NType>::value, "");
+
+static_assert(alignment_of_v<int> == alignof(int)
+	      && alignment_of<int>::value == alignof(int) , "");
+
+static_assert(rank_v<int[1][1]> == rank<int[1][1]>::value, "");
+
+static_assert(extent_v<int[1][2], 1> == 2
+	      && extent<int[1][2], 1>::value == 2, "");
+
+static_assert(is_same_v<int, int> && is_same<int, int>::value, "");
+static_assert(!is_same_v<int, char> && !is_same<int, char>::value, "");
+
+static_assert(is_base_of_v<Abstract, Poly>
+	      && is_base_of<Abstract, Poly>::value, "");
+static_assert(!is_base_of_v<Abstract, NType>
+	      && !is_base_of<Abstract, NType>::value, "");
+
+static_assert(is_convertible_v<int&, const int&>
+	      && is_convertible<int&, const int&>::value, "");
+static_assert(!is_convertible_v<const int&, int&>
+	      && !is_convertible<const int&, int&>::value, "");