diff options
Diffstat (limited to 'libstdc++-v3/include/std/type_traits')
-rw-r--r-- | libstdc++-v3/include/std/type_traits | 334 |
1 files changed, 253 insertions, 81 deletions
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 3a622eb61e0..78a113af415 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -91,6 +91,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool, typename, typename> struct conditional; + template <typename _Type> + struct __type_identity { + using type = _Type; + }; + template<typename...> struct __or_; @@ -177,6 +182,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++17 + // Forward declarations + template<typename> + struct is_reference; + template<typename> + struct is_function; + template<typename> + struct is_void; + template<typename> + struct __is_array_unknown_bounds; + + // Helper functions that return false_type for incomplete classes, + // incomplete unions and arrays of known bound from those. + + template <typename _T, size_t = sizeof(_T)> + constexpr true_type __is_complete_or_unbounded(__type_identity<_T>) + { return {}; } + + template <typename _TypeIdentity, + typename _NestedType = typename _TypeIdentity::type> + constexpr typename __or_< + is_reference<_NestedType>, + is_function<_NestedType>, + is_void<_NestedType>, + __is_array_unknown_bounds<_NestedType> + >::type __is_complete_or_unbounded(_TypeIdentity) + { return {}; } + // For several sfinae-friendly trait implementations we transport both the // result information (as the member type) and the failure information (no // member type). This is very similar to std::enable_if, but we cannot use @@ -399,9 +431,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public true_type { }; template<typename> - struct is_function; - - template<typename> struct __is_member_object_pointer_helper : public false_type { }; @@ -671,44 +700,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_trivial : public integral_constant<bool, __is_trivial(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; // is_trivially_copyable template<typename _Tp> struct is_trivially_copyable : public integral_constant<bool, __is_trivially_copyable(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_standard_layout template<typename _Tp> struct is_standard_layout : public integral_constant<bool, __is_standard_layout(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_pod // Could use is_standard_layout && is_trivial instead of the builtin. template<typename _Tp> struct is_pod : public integral_constant<bool, __is_pod(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_literal_type template<typename _Tp> struct is_literal_type : public integral_constant<bool, __is_literal_type(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_empty template<typename _Tp> struct is_empty : public integral_constant<bool, __is_empty(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_polymorphic template<typename _Tp> struct is_polymorphic : public integral_constant<bool, __is_polymorphic(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; #if __cplusplus >= 201402L #define __cpp_lib_is_final 201402L @@ -716,14 +766,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_final : public integral_constant<bool, __is_final(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; #endif /// is_abstract template<typename _Tp> struct is_abstract : public integral_constant<bool, __is_abstract(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = is_arithmetic<_Tp>::value> @@ -828,7 +884,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_destructible : public __is_destructible_safe<_Tp>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; // is_nothrow_destructible requires that is_destructible is // satisfied as well. We realize that by mimicing the @@ -876,19 +935,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_nothrow_destructible : public __is_nt_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template<typename _Tp, typename... _Args> + struct __is_constructible_impl + : public __bool_constant<__is_constructible(_Tp, _Args...)> { }; /// is_constructible template<typename _Tp, typename... _Args> struct is_constructible - : public __bool_constant<__is_constructible(_Tp, _Args...)> - { }; + : public __is_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_default_constructible template<typename _Tp> struct is_default_constructible - : public is_constructible<_Tp>::type - { }; + : public __is_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_copy_constructible_impl; @@ -899,14 +972,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_copy_constructible_impl<_Tp, true> - : public is_constructible<_Tp, const _Tp&> + : public __is_constructible_impl<_Tp, const _Tp&> { }; /// is_copy_constructible template<typename _Tp> struct is_copy_constructible : public __is_copy_constructible_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_move_constructible_impl; @@ -917,14 +993,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_move_constructible_impl<_Tp, true> - : public is_constructible<_Tp, _Tp&&> + : public __is_constructible_impl<_Tp, _Tp&&> { }; /// is_move_constructible template<typename _Tp> struct is_move_constructible : public __is_move_constructible_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp> struct __is_nt_default_constructible_atom @@ -946,12 +1025,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_nt_default_constructible_atom<_Tp> { }; + template<typename _Tp> + using __is_nothrow_default_constructible_impl + = __and_<__is_constructible_impl<_Tp>, + __is_nt_default_constructible_impl<_Tp>>; + /// is_nothrow_default_constructible template<typename _Tp> struct is_nothrow_default_constructible - : public __and_<is_default_constructible<_Tp>, - __is_nt_default_constructible_impl<_Tp>> - { }; + : public __is_nothrow_default_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, typename... _Args> struct __is_nt_constructible_impl @@ -966,16 +1052,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_nt_constructible_impl<_Tp> - : public is_nothrow_default_constructible<_Tp> + : public __is_nothrow_default_constructible_impl<_Tp> { }; - /// is_nothrow_constructible template<typename _Tp, typename... _Args> - struct is_nothrow_constructible - : public __and_<is_constructible<_Tp, _Args...>, + struct __is_nothrow_constructible_impl + : public __and_<__is_constructible_impl<_Tp, _Args...>, __is_nt_constructible_impl<_Tp, _Args...>> { }; + /// is_nothrow_constructible + template<typename _Tp, typename... _Args> + struct is_nothrow_constructible + : public __is_nothrow_constructible_impl<_Tp, _Args...>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_nothrow_copy_constructible_impl; @@ -985,14 +1079,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_nothrow_copy_constructible_impl<_Tp, true> - : public is_nothrow_constructible<_Tp, const _Tp&> + : public __is_nothrow_constructible_impl<_Tp, const _Tp&> { }; /// is_nothrow_copy_constructible template<typename _Tp> struct is_nothrow_copy_constructible - : public __is_nothrow_copy_constructible_impl<_Tp> - { }; + : public __is_nothrow_copy_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_nothrow_move_constructible_impl; @@ -1003,20 +1100,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_nothrow_move_constructible_impl<_Tp, true> - : public is_nothrow_constructible<_Tp, _Tp&&> + : public __is_nothrow_constructible_impl<_Tp, _Tp&&> { }; /// is_nothrow_move_constructible template<typename _Tp> struct is_nothrow_move_constructible - : public __is_nothrow_move_constructible_impl<_Tp> - { }; + : public __is_nothrow_move_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_assignable template<typename _Tp, typename _Up> struct is_assignable - : public __bool_constant<__is_assignable(_Tp, _Up)> - { }; + : public __bool_constant<__is_assignable(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_copy_assignable_impl; @@ -1027,14 +1130,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_copy_assignable_impl<_Tp, true> - : public is_assignable<_Tp&, const _Tp&> + : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> { }; /// is_copy_assignable template<typename _Tp> struct is_copy_assignable - : public __is_copy_assignable_impl<_Tp> - { }; + : public __is_copy_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_move_assignable_impl; @@ -1045,27 +1151,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_move_assignable_impl<_Tp, true> - : public is_assignable<_Tp&, _Tp&&> + : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> { }; /// is_move_assignable template<typename _Tp> struct is_move_assignable - : public __is_move_assignable_impl<_Tp> - { }; + : public __is_move_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, typename _Up> struct __is_nt_assignable_impl : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())> { }; - /// is_nothrow_assignable template<typename _Tp, typename _Up> - struct is_nothrow_assignable - : public __and_<is_assignable<_Tp, _Up>, + struct __is_nothrow_assignable_impl + : public __and_<__bool_constant<__is_assignable(_Tp, _Up)>, __is_nt_assignable_impl<_Tp, _Up>> { }; + /// is_nothrow_assignable + template<typename _Tp, typename _Up> + struct is_nothrow_assignable + : public __is_nothrow_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_nt_copy_assignable_impl; @@ -1075,14 +1192,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_nt_copy_assignable_impl<_Tp, true> - : public is_nothrow_assignable<_Tp&, const _Tp&> + : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> { }; /// is_nothrow_copy_assignable template<typename _Tp> struct is_nothrow_copy_assignable : public __is_nt_copy_assignable_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_nt_move_assignable_impl; @@ -1093,26 +1213,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_nt_move_assignable_impl<_Tp, true> - : public is_nothrow_assignable<_Tp&, _Tp&&> + : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> { }; /// is_nothrow_move_assignable template<typename _Tp> struct is_nothrow_move_assignable : public __is_nt_move_assignable_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_trivially_constructible template<typename _Tp, typename... _Args> struct is_trivially_constructible : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_trivially_default_constructible template<typename _Tp> struct is_trivially_default_constructible - : public is_trivially_constructible<_Tp>::type - { }; + : public __bool_constant<__is_trivially_constructible(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; struct __do_is_implicitly_default_constructible_impl { @@ -1140,12 +1269,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Tp> struct __is_implicitly_default_constructible - : public __and_<is_default_constructible<_Tp>, + : public __and_<__is_constructible_impl<_Tp>, __is_implicitly_default_constructible_safe<_Tp>> { }; - /// is_trivially_copy_constructible - template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_trivially_copy_constructible_impl; @@ -1155,17 +1282,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_trivially_copy_constructible_impl<_Tp, true> - : public __and_<is_copy_constructible<_Tp>, + : public __and_<__is_copy_constructible_impl<_Tp>, integral_constant<bool, __is_trivially_constructible(_Tp, const _Tp&)>> { }; + /// is_trivially_copy_constructible template<typename _Tp> struct is_trivially_copy_constructible : public __is_trivially_copy_constructible_impl<_Tp> - { }; - - /// is_trivially_move_constructible + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_trivially_move_constructible_impl; @@ -1176,23 +1305,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct __is_trivially_move_constructible_impl<_Tp, true> - : public __and_<is_move_constructible<_Tp>, + : public __and_<__is_move_constructible_impl<_Tp>, integral_constant<bool, __is_trivially_constructible(_Tp, _Tp&&)>> { }; + /// is_trivially_move_constructible template<typename _Tp> struct is_trivially_move_constructible : public __is_trivially_move_constructible_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_trivially_assignable template<typename _Tp, typename _Up> struct is_trivially_assignable : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> - { }; - - /// is_trivially_copy_assignable + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_trivially_copy_assignable_impl; @@ -1206,12 +1340,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> { }; + /// is_trivially_copy_assignable template<typename _Tp> struct is_trivially_copy_assignable : public __is_trivially_copy_assignable_impl<_Tp> - { }; - - /// is_trivially_move_assignable + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp, bool = __is_referenceable<_Tp>::value> struct __is_trivially_move_assignable_impl; @@ -1225,24 +1361,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> { }; + /// is_trivially_move_assignable template<typename _Tp> struct is_trivially_move_assignable : public __is_trivially_move_assignable_impl<_Tp> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_trivially_destructible template<typename _Tp> struct is_trivially_destructible - : public __and_<is_destructible<_Tp>, + : public __and_<__is_destructible_safe<_Tp>, __bool_constant<__has_trivial_destructor(_Tp)>> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// has_virtual_destructor template<typename _Tp> struct has_virtual_destructor : public integral_constant<bool, __has_virtual_destructor(_Tp)> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; // type property queries. @@ -1250,7 +1396,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// alignment_of template<typename _Tp> struct alignment_of - : public integral_constant<std::size_t, alignof(_Tp)> { }; + : public integral_constant<std::size_t, alignof(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// rank template<typename> @@ -1336,7 +1486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_convertible_helper<_From, _To>::type { }; - template<typename _From, typename _To, + template<typename _From, typename _To, bool = __or_<is_void<_From>, is_function<_To>, is_array<_To>>::value> struct __is_nt_convertible_helper @@ -2577,13 +2727,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct is_swappable : public __is_swappable_impl<_Tp>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_nothrow_swappable template<typename _Tp> struct is_nothrow_swappable : public __is_nothrow_swappable_impl<_Tp>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; #if __cplusplus >= 201402L /// is_swappable_v @@ -2774,20 +2930,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Fn, typename... _ArgTypes> struct is_invocable : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; /// std::is_invocable_r template<typename _Ret, typename _Fn, typename... _ArgTypes> struct is_invocable_r : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; /// std::is_nothrow_invocable template<typename _Fn, typename... _ArgTypes> struct is_nothrow_invocable : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, - __call_is_nothrow_<_Fn, _ArgTypes...>>::type - { }; + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; template<typename _Result, typename _Ret, typename = void> struct __is_nt_invocable_impl : false_type { }; @@ -2993,7 +3158,10 @@ template <typename _From, typename _To> : bool_constant<__has_unique_object_representations( remove_cv_t<remove_all_extents_t<_Tp>> )> - { }; + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; template<typename _Tp> inline constexpr bool has_unique_object_representations_v @@ -3005,7 +3173,11 @@ template <typename _From, typename _To> /// is_aggregate template<typename _Tp> struct is_aggregate - : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> { }; + : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; /// is_aggregate_v template<typename _Tp> |