@@ -915,11 +915,221 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
915
915
: public __is_default_constructible_safe<_Tp>::type
916
916
{ };
917
917
918
+ #if __GNUC__ >= 8
918
919
// / is_constructible
919
920
template <typename _Tp, typename ... _Args>
920
921
struct is_constructible
921
922
: public __bool_constant<__is_constructible(_Tp, _Args...)>
922
923
{ };
924
+ #else
925
+ // Implementation of is_constructible.
926
+
927
+ // The hardest part of this trait is the binary direct-initialization
928
+ // case, because we hit into a functional cast of the form T(arg).
929
+ // This implementation uses different strategies depending on the
930
+ // target type to reduce the test overhead as much as possible:
931
+ //
932
+ // a) For a reference target type, we use a static_cast expression
933
+ // modulo its extra cases.
934
+ //
935
+ // b) For a non-reference target type we use a ::new expression.
936
+ struct __do_is_static_castable_impl
937
+ {
938
+ template <typename _From, typename _To, typename
939
+ = decltype (static_cast <_To>(declval<_From>()))>
940
+ static true_type __test (int );
941
+
942
+ template <typename , typename >
943
+ static false_type __test (...);
944
+ };
945
+
946
+ template <typename _From, typename _To>
947
+ struct __is_static_castable_impl
948
+ : public __do_is_static_castable_impl
949
+ {
950
+ typedef decltype (__test<_From, _To>(0 )) type;
951
+ };
952
+
953
+ template <typename _From, typename _To>
954
+ struct __is_static_castable_safe
955
+ : public __is_static_castable_impl<_From, _To>::type
956
+ { };
957
+
958
+ // __is_static_castable
959
+ template <typename _From, typename _To>
960
+ struct __is_static_castable
961
+ : public integral_constant<bool , (__is_static_castable_safe<
962
+ _From, _To>::value)>
963
+ { };
964
+
965
+ // Implementation for non-reference types. To meet the proper
966
+ // variable definition semantics, we also need to test for
967
+ // is_destructible in this case.
968
+ // This form should be simplified by a single expression:
969
+ // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
970
+ struct __do_is_direct_constructible_impl
971
+ {
972
+ template <typename _Tp, typename _Arg, typename
973
+ = decltype (::new _Tp(declval<_Arg>()))>
974
+ static true_type __test (int );
975
+
976
+ template <typename , typename >
977
+ static false_type __test (...);
978
+ };
979
+
980
+ template <typename _Tp, typename _Arg>
981
+ struct __is_direct_constructible_impl
982
+ : public __do_is_direct_constructible_impl
983
+ {
984
+ typedef decltype (__test<_Tp, _Arg>(0 )) type;
985
+ };
986
+
987
+ template <typename _Tp, typename _Arg>
988
+ struct __is_direct_constructible_new_safe
989
+ : public __and_<is_destructible<_Tp>,
990
+ __is_direct_constructible_impl<_Tp, _Arg>>
991
+ { };
992
+
993
+ template <typename , typename >
994
+ struct is_same ;
995
+
996
+ template <typename , typename >
997
+ struct is_base_of ;
998
+
999
+ template <typename >
1000
+ struct remove_reference ;
1001
+
1002
+ template <typename _From, typename _To, bool
1003
+ = __not_<__or_<is_void<_From>,
1004
+ is_function<_From>>>::value>
1005
+ struct __is_base_to_derived_ref ;
1006
+
1007
+ template <typename _Tp, typename ... _Args>
1008
+ struct is_constructible ;
1009
+
1010
+ // Detect whether we have a downcast situation during
1011
+ // reference binding.
1012
+ template <typename _From, typename _To>
1013
+ struct __is_base_to_derived_ref <_From, _To, true >
1014
+ {
1015
+ typedef typename remove_cv<typename remove_reference<_From
1016
+ >::type>::type __src_t ;
1017
+ typedef typename remove_cv<typename remove_reference<_To
1018
+ >::type>::type __dst_t ;
1019
+ typedef __and_<__not_<is_same<__src_t , __dst_t >>,
1020
+ is_base_of<__src_t , __dst_t >,
1021
+ __not_<is_constructible<__dst_t , _From>>> type;
1022
+ static constexpr bool value = type::value;
1023
+ };
1024
+
1025
+ template <typename _From, typename _To>
1026
+ struct __is_base_to_derived_ref <_From, _To, false >
1027
+ : public false_type
1028
+ { };
1029
+
1030
+ template <typename _From, typename _To, bool
1031
+ = __and_<is_lvalue_reference<_From>,
1032
+ is_rvalue_reference<_To>>::value>
1033
+ struct __is_lvalue_to_rvalue_ref ;
1034
+
1035
+ // Detect whether we have an lvalue of non-function type
1036
+ // bound to a reference-compatible rvalue-reference.
1037
+ template <typename _From, typename _To>
1038
+ struct __is_lvalue_to_rvalue_ref <_From, _To, true >
1039
+ {
1040
+ typedef typename remove_cv<typename remove_reference<
1041
+ _From>::type>::type __src_t ;
1042
+ typedef typename remove_cv<typename remove_reference<
1043
+ _To>::type>::type __dst_t ;
1044
+ typedef __and_<__not_<is_function<__src_t >>,
1045
+ __or_<is_same<__src_t , __dst_t >,
1046
+ is_base_of<__dst_t , __src_t >>> type;
1047
+ static constexpr bool value = type::value;
1048
+ };
1049
+
1050
+ template <typename _From, typename _To>
1051
+ struct __is_lvalue_to_rvalue_ref <_From, _To, false >
1052
+ : public false_type
1053
+ { };
1054
+
1055
+ // Here we handle direct-initialization to a reference type as
1056
+ // equivalent to a static_cast modulo overshooting conversions.
1057
+ // These are restricted to the following conversions:
1058
+ // a) A base class value to a derived class reference
1059
+ // b) An lvalue to an rvalue-reference of reference-compatible
1060
+ // types that are not functions
1061
+ template <typename _Tp, typename _Arg>
1062
+ struct __is_direct_constructible_ref_cast
1063
+ : public __and_<__is_static_castable<_Arg, _Tp>,
1064
+ __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
1065
+ __is_lvalue_to_rvalue_ref<_Arg, _Tp>
1066
+ >>>
1067
+ { };
1068
+
1069
+ template <typename _Tp, typename _Arg>
1070
+ struct __is_direct_constructible_new
1071
+ : public conditional<is_reference<_Tp>::value,
1072
+ __is_direct_constructible_ref_cast<_Tp, _Arg>,
1073
+ __is_direct_constructible_new_safe<_Tp, _Arg>
1074
+ >::type
1075
+ { };
1076
+
1077
+ template <typename _Tp, typename _Arg>
1078
+ struct __is_direct_constructible
1079
+ : public __is_direct_constructible_new<_Tp, _Arg>::type
1080
+ { };
1081
+
1082
+ // Since default-construction and binary direct-initialization have
1083
+ // been handled separately, the implementation of the remaining
1084
+ // n-ary construction cases is rather straightforward. We can use
1085
+ // here a functional cast, because array types are excluded anyway
1086
+ // and this form is never interpreted as a C cast.
1087
+ struct __do_is_nary_constructible_impl
1088
+ {
1089
+ template <typename _Tp, typename ... _Args, typename
1090
+ = decltype (_Tp(declval<_Args>()...))>
1091
+ static true_type __test (int );
1092
+
1093
+ template <typename , typename ...>
1094
+ static false_type __test (...);
1095
+ };
1096
+
1097
+ template <typename _Tp, typename ... _Args>
1098
+ struct __is_nary_constructible_impl
1099
+ : public __do_is_nary_constructible_impl
1100
+ {
1101
+ typedef decltype (__test<_Tp, _Args...>(0 )) type;
1102
+ };
1103
+
1104
+ template <typename _Tp, typename ... _Args>
1105
+ struct __is_nary_constructible
1106
+ : public __is_nary_constructible_impl<_Tp, _Args...>::type
1107
+ {
1108
+ static_assert (sizeof ...(_Args) > 1 ,
1109
+ " Only useful for > 1 arguments" );
1110
+ };
1111
+
1112
+ template <typename _Tp, typename ... _Args>
1113
+ struct __is_constructible_impl
1114
+ : public __is_nary_constructible<_Tp, _Args...>
1115
+ { };
1116
+
1117
+ template <typename _Tp, typename _Arg>
1118
+ struct __is_constructible_impl <_Tp, _Arg>
1119
+ : public __is_direct_constructible<_Tp, _Arg>
1120
+ { };
1121
+
1122
+ template <typename _Tp>
1123
+ struct __is_constructible_impl <_Tp>
1124
+ : public is_default_constructible<_Tp>
1125
+ { };
1126
+
1127
+ // / is_constructible
1128
+ template <typename _Tp, typename ... _Args>
1129
+ struct is_constructible
1130
+ : public __is_constructible_impl<_Tp, _Args...>::type
1131
+ { };
1132
+ #endif
923
1133
924
1134
template <typename _Tp, bool = __is_referenceable<_Tp>::value>
925
1135
struct __is_copy_constructible_impl ;
@@ -1043,11 +1253,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1043
1253
: public __is_nothrow_move_constructible_impl<_Tp>
1044
1254
{ };
1045
1255
1256
+ #if __GNUC__ >= 8
1046
1257
// / is_assignable
1047
1258
template <typename _Tp, typename _Up>
1048
1259
struct is_assignable
1049
1260
: public __bool_constant<__is_assignable(_Tp, _Up)>
1050
1261
{ };
1262
+ #else
1263
+ template <typename _Tp, typename _Up>
1264
+ class __is_assignable_helper
1265
+ {
1266
+ template <typename _Tp1, typename _Up1,
1267
+ typename = decltype (declval<_Tp1>() = declval<_Up1>())>
1268
+ static true_type
1269
+ __test (int );
1270
+
1271
+ template <typename , typename >
1272
+ static false_type
1273
+ __test (...);
1274
+
1275
+ public:
1276
+ typedef decltype (__test<_Tp, _Up>(0 )) type;
1277
+ };
1278
+
1279
+ // / is_assignable
1280
+ template <typename _Tp, typename _Up>
1281
+ struct is_assignable
1282
+ : public __is_assignable_helper<_Tp, _Up>::type
1283
+ { };
1284
+ #endif
1051
1285
1052
1286
template <typename _Tp, bool = __is_referenceable<_Tp>::value>
1053
1287
struct __is_copy_assignable_impl ;
0 commit comments