@@ -896,11 +896,257 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
896
896
" template argument must be a complete class or an unbounded array" );
897
897
};
898
898
899
+ #if __GNUC__ >= 8
899
900
template <typename _Tp, typename ... _Args>
900
901
struct __is_constructible_impl
901
902
: public __bool_constant<__is_constructible(_Tp, _Args...)>
903
+ { };
904
+ #else
905
+ // Implementation of __is_constructible_impl.
906
+
907
+ struct __do_is_default_constructible_impl
908
+ {
909
+ template <typename _Tp, typename = decltype(_Tp())>
910
+ static true_type __test (int );
911
+
912
+ template <typename >
913
+ static false_type __test (...);
914
+ };
915
+
916
+ template <typename _Tp>
917
+ struct __is_default_constructible_impl
918
+ : public __do_is_default_constructible_impl
919
+ {
920
+ typedef decltype (__test<_Tp>(0 )) type;
921
+ };
922
+
923
+ template <typename _Tp>
924
+ struct __is_default_constructible_atom
925
+ : public __and_<__not_<is_void<_Tp>>,
926
+ __is_default_constructible_impl<_Tp>>::type
927
+ { };
928
+
929
+ template <typename _Tp, bool = is_array<_Tp>::value>
930
+ struct __is_default_constructible_safe ;
931
+
932
+ // The following technique is a workaround for a current core language
933
+ // restriction, which does not allow for array types to occur in
934
+ // functional casts of the form T(). Complete arrays can be default-
935
+ // constructed, if the element type is default-constructible, but
936
+ // arrays with unknown bounds are not.
937
+ template <typename _Tp>
938
+ struct __is_default_constructible_safe <_Tp, true >
939
+ : public __and_<__is_array_known_bounds<_Tp>,
940
+ __is_default_constructible_atom<typename
941
+ remove_all_extents<_Tp>::type>>::type
942
+ { };
943
+
944
+ template <typename _Tp>
945
+ struct __is_default_constructible_safe <_Tp, false >
946
+ : public __is_default_constructible_atom<_Tp>::type
947
+ { };
948
+
949
+ // The hardest part of this trait is the binary direct-initialization
950
+ // case, because we hit into a functional cast of the form T(arg).
951
+ // This implementation uses different strategies depending on the
952
+ // target type to reduce the test overhead as much as possible:
953
+ //
954
+ // a) For a reference target type, we use a static_cast expression
955
+ // modulo its extra cases.
956
+ //
957
+ // b) For a non-reference target type we use a ::new expression.
958
+ struct __do_is_static_castable_impl
959
+ {
960
+ template <typename _From, typename _To, typename
961
+ = decltype(static_cast <_To>(declval<_From>()))>
962
+ static true_type __test (int );
963
+
964
+ template <typename , typename >
965
+ static false_type __test (...);
966
+ };
967
+
968
+ template <typename _From, typename _To>
969
+ struct __is_static_castable_impl
970
+ : public __do_is_static_castable_impl
971
+ {
972
+ typedef decltype (__test<_From, _To>(0 )) type;
973
+ };
974
+
975
+ template <typename _From, typename _To>
976
+ struct __is_static_castable_safe
977
+ : public __is_static_castable_impl<_From, _To>::type
978
+ { };
979
+
980
+ // __is_static_castable
981
+ template <typename _From, typename _To>
982
+ struct __is_static_castable
983
+ : public integral_constant<bool , (__is_static_castable_safe<
984
+ _From, _To>::value)>
985
+ { };
986
+
987
+ // Implementation for non-reference types. To meet the proper
988
+ // variable definition semantics, we also need to test for
989
+ // is_destructible in this case.
990
+ // This form should be simplified by a single expression:
991
+ // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
992
+ struct __do_is_direct_constructible_impl
993
+ {
994
+ template <typename _Tp, typename _Arg, typename
995
+ = decltype(::new _Tp(declval<_Arg>()))>
996
+ static true_type __test (int );
997
+
998
+ template <typename , typename >
999
+ static false_type __test (...);
1000
+ };
1001
+
1002
+ template <typename _Tp, typename _Arg>
1003
+ struct __is_direct_constructible_impl
1004
+ : public __do_is_direct_constructible_impl
1005
+ {
1006
+ typedef decltype (__test<_Tp, _Arg>(0 )) type;
1007
+ };
1008
+
1009
+ template <typename _Tp, typename _Arg>
1010
+ struct __is_direct_constructible_new_safe
1011
+ : public __and_<is_destructible<_Tp>,
1012
+ __is_direct_constructible_impl<_Tp, _Arg>>
1013
+ { };
1014
+
1015
+ template <typename , typename >
1016
+ struct is_same ;
1017
+
1018
+ template <typename , typename >
1019
+ struct is_base_of ;
1020
+
1021
+ template <typename >
1022
+ struct remove_reference ;
1023
+
1024
+ template <typename _From, typename _To, bool
1025
+ = __not_<__or_<is_void<_From>,
1026
+ is_function<_From>>>::value>
1027
+ struct __is_base_to_derived_ref ;
1028
+
1029
+ template <typename _Tp, typename ... _Args>
1030
+ struct is_constructible ;
1031
+
1032
+ // Detect whether we have a downcast situation during
1033
+ // reference binding.
1034
+ template <typename _From, typename _To>
1035
+ struct __is_base_to_derived_ref <_From, _To, true >
1036
+ {
1037
+ typedef typename remove_cv<typename remove_reference<_From
1038
+ >::type>::type __src_t ;
1039
+ typedef typename remove_cv<typename remove_reference<_To
1040
+ >::type>::type __dst_t ;
1041
+ typedef __and_<__not_<is_same<__src_t , __dst_t >>,
1042
+ is_base_of<__src_t , __dst_t >,
1043
+ __not_<is_constructible<__dst_t , _From>>> type;
1044
+ static constexpr bool value = type::value;
1045
+ };
1046
+
1047
+ template <typename _From, typename _To>
1048
+ struct __is_base_to_derived_ref <_From, _To, false >
1049
+ : public false_type
1050
+ { };
1051
+
1052
+ template <typename _From, typename _To, bool
1053
+ = __and_<is_lvalue_reference<_From>,
1054
+ is_rvalue_reference<_To>>::value>
1055
+ struct __is_lvalue_to_rvalue_ref ;
1056
+
1057
+ // Detect whether we have an lvalue of non-function type
1058
+ // bound to a reference-compatible rvalue-reference.
1059
+ template <typename _From, typename _To>
1060
+ struct __is_lvalue_to_rvalue_ref <_From, _To, true >
1061
+ {
1062
+ typedef typename remove_cv<typename remove_reference<
1063
+ _From>::type>::type __src_t ;
1064
+ typedef typename remove_cv<typename remove_reference<
1065
+ _To>::type>::type __dst_t ;
1066
+ typedef __and_<__not_<is_function<__src_t >>,
1067
+ __or_<is_same<__src_t , __dst_t >,
1068
+ is_base_of<__dst_t , __src_t >>> type;
1069
+ static constexpr bool value = type::value;
1070
+ };
1071
+
1072
+ template <typename _From, typename _To>
1073
+ struct __is_lvalue_to_rvalue_ref <_From, _To, false >
1074
+ : public false_type
1075
+ { };
1076
+
1077
+ // Here we handle direct-initialization to a reference type as
1078
+ // equivalent to a static_cast modulo overshooting conversions.
1079
+ // These are restricted to the following conversions:
1080
+ // a) A base class value to a derived class reference
1081
+ // b) An lvalue to an rvalue-reference of reference-compatible
1082
+ // types that are not functions
1083
+ template <typename _Tp, typename _Arg>
1084
+ struct __is_direct_constructible_ref_cast
1085
+ : public __and_<__is_static_castable<_Arg, _Tp>,
1086
+ __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
1087
+ __is_lvalue_to_rvalue_ref<_Arg, _Tp>
1088
+ >>>
1089
+ { };
1090
+
1091
+ template <typename _Tp, typename _Arg>
1092
+ struct __is_direct_constructible_new
1093
+ : public conditional<is_reference<_Tp>::value,
1094
+ __is_direct_constructible_ref_cast<_Tp, _Arg>,
1095
+ __is_direct_constructible_new_safe<_Tp, _Arg>
1096
+ >::type
1097
+ { };
1098
+
1099
+ template <typename _Tp, typename _Arg>
1100
+ struct __is_direct_constructible
1101
+ : public __is_direct_constructible_new<_Tp, _Arg>::type
1102
+ { };
1103
+
1104
+ // Since default-construction and binary direct-initialization have
1105
+ // been handled separately, the implementation of the remaining
1106
+ // n-ary construction cases is rather straightforward. We can use
1107
+ // here a functional cast, because array types are excluded anyway
1108
+ // and this form is never interpreted as a C cast.
1109
+ struct __do_is_nary_constructible_impl
1110
+ {
1111
+ template <typename _Tp, typename ... _Args, typename
1112
+ = decltype(_Tp(declval<_Args>()...))>
1113
+ static true_type __test (int );
1114
+
1115
+ template <typename , typename ...>
1116
+ static false_type __test (...);
1117
+ };
1118
+
1119
+ template <typename _Tp, typename ... _Args>
1120
+ struct __is_nary_constructible_impl
1121
+ : public __do_is_nary_constructible_impl
1122
+ {
1123
+ typedef decltype (__test<_Tp, _Args...>(0 )) type;
1124
+ };
1125
+
1126
+ template <typename _Tp, typename ... _Args>
1127
+ struct __is_nary_constructible
1128
+ : public __is_nary_constructible_impl<_Tp, _Args...>::type
1129
+ {
1130
+ static_assert (sizeof ...(_Args) > 1 ,
1131
+ " Only useful for > 1 arguments" );
1132
+ };
1133
+
1134
+ template <typename _Tp, typename ... _Args>
1135
+ struct __is_constructible_impl
1136
+ : public __is_nary_constructible<_Tp, _Args...>
902
1137
{ };
903
1138
1139
+ template <typename _Tp, typename _Arg>
1140
+ struct __is_constructible_impl <_Tp, _Arg>
1141
+ : public __is_direct_constructible<_Tp, _Arg>
1142
+ { };
1143
+
1144
+ template <typename _Tp>
1145
+ struct __is_constructible_impl <_Tp>
1146
+ : public __is_default_constructible_safe<_Tp>::type
1147
+ { };
1148
+ #endif
1149
+
904
1150
// / is_constructible
905
1151
template <typename _Tp, typename ... _Args>
906
1152
struct is_constructible
@@ -998,10 +1244,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
998
1244
{ };
999
1245
#endif
1000
1246
1247
+ #if __GNUC__ >= 8
1001
1248
template <typename _Tp, typename ... _Args>
1002
1249
using __is_nothrow_constructible_impl
1003
1250
= __is_nt_constructible_impl<__is_constructible (_Tp, _Args...),
1004
1251
_Tp, _Args...>;
1252
+ #else
1253
+ template <typename _Tp, typename ... _Args>
1254
+ using __is_nothrow_constructible_impl
1255
+ = __is_nt_constructible_impl<__is_constructible_impl<_Tp, _Args...>::value,
1256
+ _Tp, _Args...>;
1257
+ #endif
1005
1258
1006
1259
// / is_nothrow_constructible
1007
1260
template <typename _Tp, typename ... _Args>
@@ -1064,6 +1317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1064
1317
" template argument must be a complete class or an unbounded array" );
1065
1318
};
1066
1319
1320
+ #if __GNUC__ >= 8
1067
1321
// / is_assignable
1068
1322
template <typename _Tp, typename _Up>
1069
1323
struct is_assignable
@@ -1072,6 +1326,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1072
1326
static_assert (std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
1073
1327
" template argument must be a complete class or an unbounded array" );
1074
1328
};
1329
+ #else
1330
+ template <typename _Tp, typename _Up>
1331
+ class __is_assignable_helper
1332
+ {
1333
+ template <typename _Tp1, typename _Up1,
1334
+ typename = decltype(declval<_Tp1>() = declval<_Up1>())>
1335
+ static true_type
1336
+ __test (int );
1337
+
1338
+ template <typename , typename >
1339
+ static false_type
1340
+ __test (...);
1341
+
1342
+ public:
1343
+ typedef decltype (__test<_Tp, _Up>(0 )) type;
1344
+ };
1345
+
1346
+ // / is_assignable
1347
+ template <typename _Tp, typename _Up>
1348
+ struct is_assignable
1349
+ : public __is_assignable_helper<_Tp, _Up>::type
1350
+ { };
1351
+ #endif
1075
1352
1076
1353
template <typename _Tp, bool = __is_referenceable<_Tp>::value>
1077
1354
struct __is_copy_assignable_impl ;
@@ -1080,10 +1357,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1080
1357
struct __is_copy_assignable_impl <_Tp, false >
1081
1358
: public false_type { };
1082
1359
1360
+ #if __GNUC__ >= 8
1083
1361
template <typename _Tp>
1084
1362
struct __is_copy_assignable_impl <_Tp, true >
1085
1363
: public __bool_constant<__is_assignable(_Tp&, const _Tp&)>
1086
1364
{ };
1365
+ #else
1366
+ template <typename _Tp>
1367
+ struct __is_copy_assignable_impl <_Tp, true >
1368
+ : public is_assignable<_Tp&, const _Tp&>
1369
+ { };
1370
+ #endif
1087
1371
1088
1372
// / is_copy_assignable
1089
1373
template <typename _Tp>
@@ -1101,10 +1385,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1101
1385
struct __is_move_assignable_impl <_Tp, false >
1102
1386
: public false_type { };
1103
1387
1388
+ #if __GNUC__ >= 8
1104
1389
template <typename _Tp>
1105
1390
struct __is_move_assignable_impl <_Tp, true >
1106
1391
: public __bool_constant<__is_assignable(_Tp&, _Tp&&)>
1107
1392
{ };
1393
+ #else
1394
+ template <typename _Tp>
1395
+ struct __is_move_assignable_impl <_Tp, true >
1396
+ : public is_assignable<_Tp&, _Tp&&>
1397
+ { };
1398
+ #endif
1108
1399
1109
1400
// / is_move_assignable
1110
1401
template <typename _Tp>
@@ -1120,11 +1411,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
1120
1411
: public integral_constant<bool , noexcept (declval<_Tp>() = declval<_Up>())>
1121
1412
{ };
1122
1413
1414
+ #if __GNUC__ >= 8
1123
1415
template <typename _Tp, typename _Up>
1124
1416
struct __is_nothrow_assignable_impl
1125
1417
: public __and_<__bool_constant<__is_assignable(_Tp, _Up)>,
1126
1418
__is_nt_assignable_impl<_Tp, _Up>>
1127
1419
{ };
1420
+ #else
1421
+ template <typename _Tp, typename _Up>
1422
+ struct __is_nothrow_assignable_impl
1423
+ : public __and_<is_assignable<_Tp&, _Tp&&>,
1424
+ __is_nt_assignable_impl<_Tp, _Up>>
1425
+ { };
1426
+ #endif
1128
1427
1129
1428
// / is_nothrow_assignable
1130
1429
template <typename _Tp, typename _Up>
0 commit comments