diff --git a/MsgPack/util/ArxContainer/ArxContainer.h b/MsgPack/util/ArxContainer/ArxContainer.h index 0d1f9ec..d6ed42a 100644 --- a/MsgPack/util/ArxContainer/ArxContainer.h +++ b/MsgPack/util/ArxContainer/ArxContainer.h @@ -27,7 +27,13 @@ #define ARX_MAP_DEFAULT_SIZE 16 #endif // ARX_MAP_DEFAULT_SIZE -#ifndef ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED +// Initializer_list *must* be defined in std, so take extra care to only +// define it when is really not available (e.g. +// ArduinoSTL is C++98 but *does* define ) and not +// already defined (e.g. by ArxContainer). +#if __has_include() +#include +#elif !(defined(ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED)) #define ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED namespace std { diff --git a/MsgPack/util/ArxTypeTraits/ArxTypeTraits.h b/MsgPack/util/ArxTypeTraits/ArxTypeTraits.h index a9c49b4..2aa3f5c 100644 --- a/MsgPack/util/ArxTypeTraits/ArxTypeTraits.h +++ b/MsgPack/util/ArxTypeTraits/ArxTypeTraits.h @@ -3,26 +3,52 @@ #ifndef ARX_TYPE_TRAITS_H #define ARX_TYPE_TRAITS_H -#if defined(ARDUINO_ARCH_AVR)\ - || defined(ARDUINO_ARCH_MEGAAVR)\ - || defined(ARDUINO_ARCH_SAM)\ - || defined(ARDUINO_ARCH_SAMD)\ - || defined(ARDUINO_spresense_ast) - #define ARX_TYPE_TRAITS_DISABLED - #if defined(ARDUINO_ARCH_MEGAAVR)\ - || defined(ARDUINO_ARCH_SAMD)\ - || defined(ARDUINO_spresense_ast) - #define ARX_TYPE_TRAITS_NEW_DISABLED +#if !defined(ARX_HAVE_LIBSTDCPLUSPLUS) + #if !defined(__has_include) + #error "Compiler does not support __has_include, please report a bug against the ArxTypeTraits library about this." + #endif + #if __has_include() + #include + #if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) + // For gcc's libstdc++ and clang's libc++, assume that + // __cplusplus tells us what the standard includes support + #define ARX_HAVE_LIBSTDCPLUSPLUS __cplusplus + #elif defined(__UCLIBCXX_MAJOR__) + // For uclibc++, assume C++98 support only. + #define ARX_HAVE_LIBSTDCPLUSPLUS 199711L + #else + #error "Unknown C++ library found, please report a bug against the ArxTypeTraits library about this." + #endif + #else + // Assume no standard library is available at all (e.g. on AVR) + #define ARX_HAVE_LIBSTDCPLUSPLUS 0 #endif #endif -#include -#ifndef ARX_TYPE_TRAITS_DISABLED - #include - #include - #include -#endif +// Make sure std namespace exists +namespace std { } + +// Import everything from the std namespace into arx::std. This includes +// everything yet to be defined, so we can do this early (and must do +// so, to allow e.g. the C++14 additions in the arx::std namespace to +// reference the C++11 stuff from the system headers. +namespace arx { + namespace arx_std { + using namespace ::std; + } +} + +// Import everything from arx::arx_std back into the normal std namespace. +// This ensures that you can just use `std::foo` everywhere and you get +// the standard library version if it is available, falling back to arx +// versions for things not supplied by the standard library. Only when +// you really need the arx version (e.g. for constexpr numeric_limits +// when also using ArduinoSTL), you need to qualify with arx::arx_std:: +namespace std { + using namespace ::arx::arx_std; +} +#include "ArxTypeTraits/replace_minmax_macros.h" #include "ArxTypeTraits/type_traits.h" #endif // ARX_TYPE_TRAITS_H diff --git a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/functional.h b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/functional.h index ed1ff17..7c61927 100644 --- a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/functional.h +++ b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/functional.h @@ -3,23 +3,32 @@ #ifndef ARX_TYPE_TRAITS_FUNCTIONAL_H #define ARX_TYPE_TRAITS_FUNCTIONAL_H -#include - -#ifdef ARX_TYPE_TRAITS_NEW_DISABLED - void* operator new (const size_t size, void* ptr) { (void)size; return ptr; } +// If we have a header, include it and assume it has placement new +// (for AVR this has always been true, MEGAAVR does not have placement +// new now, but will probably get it before is added). +// This also handles the case where ArduinoSTL is used, which defines an +// inline placement new which would conflict with the below definition. +#if __has_include() +#include #else - #include +// When there is no header, there might be a header, but +// not all Arduino platform (versions) define a placement new operator +// in there. +// However, it is hard to detect whether it is or is not defined, but +// the versions that do define it, do not define it inline in the +// header, so we can just define it inline here without conflicts. +// Note that there is no need to include anything to declare the +// non-placement new operators, since those are implicit. +inline void* operator new (const size_t size, void* ptr) noexcept { (void)size; return ptr; } #endif -#ifdef ARX_TYPE_TRAITS_DISABLED - -namespace std { +namespace arx { namespace arx_std { // reference: // stack overflow https://stackoverflow.com/questions/32074410/stdfunction-bind-like-type-erasure-without-standard-c-library template - struct function; + class function; template class function @@ -143,7 +152,6 @@ namespace std { return static_cast(f); } -} // namespace std +} } // namespace arx::std -#endif // ARX_TYPE_TRAITS_DISABLED #endif // ARX_TYPE_TRAITS_FUNCTIONAL_H diff --git a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/replace_minmax_macros.h b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/replace_minmax_macros.h new file mode 100644 index 0000000..9668ccc --- /dev/null +++ b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/replace_minmax_macros.h @@ -0,0 +1,33 @@ +#pragma once + +#ifndef ARX_TYPE_TRAITS_REPLACE_MINMAX_MACROS_H +#define ARX_TYPE_TRAITS_REPLACE_MINMAX_MACROS_H + +// Make sure Arduino.h is actually included, since otherwise it might be +// included later and break *uses* of the min/max methods, rather than +// the declarations of it. +#include + +// These macros are defined by Arduino.h on some platforms, and conflict +// with min/max methods defined or included by ArxTypeTraits, so replace +// them with macros here. +#ifdef max + #undef max + template + constexpr auto max(T1 x, T2 y) + -> decltype(x + y) + { + return (x > y) ? x : y; + } +#endif +#ifdef min + #undef min + template + constexpr auto min(T1 x, T2 y) + -> decltype(x + y) + { + return (x < y) ? x : y; + } +#endif + +#endif // ARX_TYPE_TRAITS_REPLACE_MINMAX_MACROS_H diff --git a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/tuple.h b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/tuple.h index f8d765b..aca75d9 100644 --- a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/tuple.h +++ b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/tuple.h @@ -3,9 +3,7 @@ #ifndef ARX_TYPE_TRAITS_TUPLE_H #define ARX_TYPE_TRAITS_TUPLE_H -#ifdef ARX_TYPE_TRAITS_DISABLED - -namespace std { +namespace arx { namespace arx_std { // https://theolizer.com/cpp-school2/cpp-school2-15/ // https://wandbox.org/permlink/C0BWIzjqg4iO3kKZ @@ -71,7 +69,6 @@ namespace std { return std::tuple::type...>(std::forward::type>(args)...); } -} // namespace std +} } // namespace arx::std -#endif // ARX_TYPE_TRAITS_DISABLED #endif // ARX_TYPE_TRAITS_TUPLE_H diff --git a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/type_traits.h b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/type_traits.h index 0b1481f..91f0054 100644 --- a/MsgPack/util/ArxTypeTraits/ArxTypeTraits/type_traits.h +++ b/MsgPack/util/ArxTypeTraits/ArxTypeTraits/type_traits.h @@ -3,32 +3,42 @@ #ifndef ARX_TYPE_TRAITS_TYPE_TRAITS_H #define ARX_TYPE_TRAITS_TYPE_TRAITS_H -#ifdef ARX_TYPE_TRAITS_DISABLED +#if ARX_HAVE_LIBSTDCPLUSPLUS >= 199711L // Have libstdc++98 -#ifdef max - #undef max - template - constexpr auto max(T1 x, T2 y) - -> decltype(x + y) - { - return (x > y) ? x : y; - } -#endif -#ifdef min - #undef min - template - constexpr auto min(T1 x, T2 y) - -> decltype(x + y) +#include + +#else // Do not have libstdc++98 + +namespace arx { namespace arx_std { + + template + void swap(T& a, T& b) { - return (x < y) ? x : y; + T t = move(a); + a = move(b); + b = move(t); } -#endif +} } // namespace arx::arx_std + +#endif // Do not have libstdc++98 + + +#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 + +#include +#include +#include +#include +#include +#include + +#else // Do not have libstdc++11 -#include #include #include +#include -namespace std { +namespace arx { namespace arx_std { using nullptr_t = decltype(nullptr); @@ -266,11 +276,11 @@ namespace std { template struct is_convertible - : std::conditional < + : conditional < can_apply ::value , true_type - , typename std::conditional < - std::is_arithmetic::value && std::is_arithmetic::value, + , typename conditional < + is_arithmetic::value && is_arithmetic::value, true_type, false_type >::type @@ -287,7 +297,7 @@ namespace std { // specialization for regular functions template struct is_function : true_type {}; - // specialization for variadic functions such as std::printf + // specialization for variadic functions such as printf template struct is_function : true_type {}; // specialization for function types that have cv-qualifiers @@ -378,18 +388,17 @@ namespace std { using result_of = details::result_of; - template - void swap(T& a, T& b) - { - T t = move(a); - a = move(b); - b = move(t); - } +} } // namespace arx::arx_std - -#ifndef ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED +// Initializer_list *must* be defined in std, so take extra care to only +// define it when is really not available (e.g. +// ArduinoSTL is C++98 but *does* define ) and not +// already defined (e.g. by ArxContainer). +#if __has_include() +#include +#elif !defined(ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED) #define ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED - +namespace std { template class initializer_list { @@ -403,38 +412,38 @@ namespace std { const T *begin() const { return array; } const T *end() const { return array + len; } }; - -#endif // ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED - } // namespace std +#endif // ARX_TYPE_TRAITS_INITIALIZER_LIST_DEFINED #include "tuple.h" #include "functional.h" -#endif // ARX_TYPE_TRAITS_DISABLE_STL +#endif // Do not have libstdc++11 -#if __cplusplus < 201402L // C++11 -#if !defined(OF_VERSION_MAJOR) || !defined(TARGET_WIN32) +#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201402L // Have libstdc++14 + // Nothing to include here, relevant header files were already included + // for C++11 above. +#else // Do not have libstdc++14 -namespace std { +namespace arx { namespace arx_std { template - using enable_if_t = typename std::enable_if::type; + using enable_if_t = typename enable_if::type; template - using decay_t = typename std::decay::type; + using decay_t = typename decay::type; template - using remove_cv_t = typename std::remove_cv::type; + using remove_cv_t = typename remove_cv::type; template - using remove_const_t = typename std::remove_const::type; + using remove_const_t = typename remove_const::type; template - using remove_volatile_t = typename std::remove_volatile::type; + using remove_volatile_t = typename remove_volatile::type; template - using remove_reference_t = typename std::remove_reference::type; + using remove_reference_t = typename remove_reference::type; template - using remove_pointer_t = typename std::remove_pointer::type; + using remove_pointer_t = typename remove_pointer::type; template struct integer_sequence @@ -471,17 +480,17 @@ namespace std { template using index_sequence_for = make_index_sequence; -} // namespace std +} } // namespace arx::arx_std -#endif // !defined(OF_VERSION_MAJOR) || !defined(TARGET_WIN32) -#endif // C++11 +#endif // Do not have libstdc++14 -#if __cplusplus < 201703L // C++14 +#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201703L // Have libstdc++17 + // Nothing to include here, relevant header files were already included + // for C++11 above. +#else // Do not have libstdc++17 -namespace std { - -#if !defined(OF_VERSION_MAJOR) || !defined(TARGET_WIN32) +namespace arx { namespace arx_std { template struct Tester { using type = void; }; @@ -489,75 +498,77 @@ namespace std { using void_t = typename Tester::type; template - struct disjunction : std::false_type {}; + struct disjunction : false_type {}; template struct disjunction : Arg::type {}; template - struct disjunction : std::conditional>::type {}; + struct disjunction : conditional>::type {}; template - struct conjunction : std::true_type {}; + struct conjunction : true_type {}; template struct conjunction : Arg::type {}; template - struct conjunction : std::conditional, Arg>::type {}; + struct conjunction : conditional, Arg>::type {}; template - struct negation : std::integral_constant {}; - -#endif // !defined(OF_VERSION_MAJOR) || !defined(TARGET_WIN32) + struct negation : integral_constant {}; // https://qiita.com/_EnumHack/items/92e6e135174f1f781dbb // without decltype(auto) template constexpr auto apply_impl(F&& f, Tuple&& t, index_sequence) - -> decltype(f(std::get(std::forward(t))...)) + -> decltype(f(get(forward(t))...)) { - return f(std::get(std::forward(t))...); + return f(get(forward(t))...); } template constexpr auto apply(F&& f, Tuple&& t) -> decltype(apply_impl( - std::forward(f), - std::forward(t), - make_index_sequence>::value>{} + forward(f), + forward(t), + make_index_sequence>::value>{} )) { return apply_impl( - std::forward(f), - std::forward(t), - make_index_sequence>::value>() + forward(f), + forward(t), + make_index_sequence>::value>() ); } -} // namespace std +} } // namespace arx::arx_std -#endif // C++14 +#endif // Do not have libstdc++17 -// C++17, C++2a -namespace std { +#if ARX_HAVE_LIBSTDCPLUSPLUS > 201703L // Have libstdc++2a + // Nothing to include here, relevant header files were already included + // for C++11 above. +#else // Do not have libstdc++2a + +namespace arx { namespace arx_std { template struct remove_cvref { - typedef std::remove_cv_t> type; + typedef remove_cv_t> type; }; template< class T > using remove_cvref_t = typename remove_cvref::type; -} // namespace std -// C++17, C++2a +} } // namespace arx::arx_std +#endif // Do not have libstdc++2a namespace arx { // others template class Check, class... T> - struct is_detected_impl : std::false_type {}; + struct is_detected_impl : arx_std::false_type {}; template