Skip to content

Commit 1e245c1

Browse files
committed
Fix compilation with avr-gcc 7
1 parent 44199da commit 1e245c1

File tree

2 files changed

+294
-0
lines changed

2 files changed

+294
-0
lines changed

include/type_traits

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,11 +915,221 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
915915
: public __is_default_constructible_safe<_Tp>::type
916916
{ };
917917

918+
#if __GNUC__ >= 8
918919
/// is_constructible
919920
template<typename _Tp, typename... _Args>
920921
struct is_constructible
921922
: public __bool_constant<__is_constructible(_Tp, _Args...)>
922923
{ };
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
9231133

9241134
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
9251135
struct __is_copy_constructible_impl;
@@ -1043,11 +1253,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
10431253
: public __is_nothrow_move_constructible_impl<_Tp>
10441254
{ };
10451255

1256+
#if __GNUC__ >= 8
10461257
/// is_assignable
10471258
template<typename _Tp, typename _Up>
10481259
struct is_assignable
10491260
: public __bool_constant<__is_assignable(_Tp, _Up)>
10501261
{ };
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
10511285

10521286
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
10531287
struct __is_copy_assignable_impl;

include/utility

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
288288
// extract the elements in a tuple.
289289
template<size_t... _Indexes> struct _Index_tuple { };
290290

291+
#if __GNUC__ >= 8 || defined(_GLIBCXX_USE_MAKE_INTEGER_SEQ)
292+
291293
#ifdef __has_builtin
292294
# if __has_builtin(__make_integer_seq)
293295
# define _GLIBCXX_USE_MAKE_INTEGER_SEQ 1
@@ -307,11 +309,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
307309
using __type = _Index_tuple<__integer_pack(_Num)...>;
308310
#endif
309311
};
312+
#else
313+
// Concatenates two _Index_tuples.
314+
template<typename _Itup1, typename _Itup2> struct _Itup_cat;
315+
316+
template<size_t... _Ind1, size_t... _Ind2>
317+
struct _Itup_cat<_Index_tuple<_Ind1...>, _Index_tuple<_Ind2...>>
318+
{
319+
using __type = _Index_tuple<_Ind1..., (_Ind2 + sizeof...(_Ind1))...>;
320+
};
321+
322+
// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
323+
template<size_t _Num>
324+
struct _Build_index_tuple
325+
: _Itup_cat<typename _Build_index_tuple<_Num / 2>::__type,
326+
typename _Build_index_tuple<_Num - _Num / 2>::__type>
327+
{ };
328+
329+
template<>
330+
struct _Build_index_tuple<1>
331+
{
332+
typedef _Index_tuple<0> __type;
333+
};
334+
335+
template<>
336+
struct _Build_index_tuple<0>
337+
{
338+
typedef _Index_tuple<> __type;
339+
};
340+
#endif // __GNUC__ >= 8 || defined(_GLIBCXX_USE_MAKE_INTEGER_SEQ)
310341

311342
#if __cplusplus > 201103L
312343

313344
#define __cpp_lib_integer_sequence 201304
314345

346+
#if __GNUC__ >= 8 || defined(_GLIBCXX_USE_MAKE_INTEGER_SEQ)
315347
/// Class template integer_sequence
316348
template<typename _Tp, _Tp... _Idx>
317349
struct integer_sequence
@@ -331,6 +363,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
331363

332364
#undef _GLIBCXX_USE_MAKE_INTEGER_SEQ
333365

366+
#else
367+
/// Class template integer_sequence
368+
template<typename _Tp, _Tp... _Idx>
369+
struct integer_sequence
370+
{
371+
typedef _Tp value_type;
372+
static constexpr size_t size() { return sizeof...(_Idx); }
373+
};
374+
375+
template<typename _Tp, _Tp _Num,
376+
typename _ISeq = typename _Build_index_tuple<_Num>::__type>
377+
struct _Make_integer_sequence;
378+
379+
template<typename _Tp, _Tp _Num, size_t... _Idx>
380+
struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>>
381+
{
382+
static_assert( _Num >= 0,
383+
"Cannot make integer sequence of negative length" );
384+
385+
typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type;
386+
};
387+
388+
/// Alias template make_integer_sequence
389+
template<typename _Tp, _Tp _Num>
390+
using make_integer_sequence
391+
= typename _Make_integer_sequence<_Tp, _Num>::__type;
392+
#endif // __GNUC__ >= 8 || defined(_GLIBCXX_USE_MAKE_INTEGER_SEQ)
393+
334394
/// Alias template index_sequence
335395
template<size_t... _Idx>
336396
using index_sequence = integer_sequence<size_t, _Idx...>;

0 commit comments

Comments
 (0)