Commits and constructive criticism are welcome
namespace detail { template <class> struct _is_floating_point : public false_type {}; template<> struct _is_floating_point<float> : public true_type {}; template<> struct _is_floating_point<double> : public true_type {}; template<> struct _is_floating_point<long double> : public true_type {}; } template <class _Tp> struct is_floating_point : public detail::_is_floating_point<typename remove_cv<_Tp>::type> { };
namespace detail { template <class> struct _is_integral_impl : public false_type {}; template<> struct _is_integral_impl<bool> : public true_type {}; template<> struct _is_integral_impl<char> : public true_type {}; template<> struct _is_integral_impl<wchar_t> : public true_type {}; template<> struct _is_integral_impl<unsigned char> : public true_type {}; template<> struct _is_integral_impl<unsigned short int> : public true_type {}; template<> struct _is_integral_impl<unsigned int> : public true_type {}; template<> struct _is_integral_impl<unsigned long int> : public true_type {}; #ifdef LLONG_MAX template<> struct _is_integral_impl<unsigned long long int> : public true_type {}; #endif template<> struct _is_integral_impl<signed char> : public true_type {}; template<> struct _is_integral_impl<short int> : public true_type {}; template<> struct _is_integral_impl<int> : public true_type {}; template<> struct _is_integral_impl<long int> : public true_type {}; #ifdef LLONG_MAX template<> struct _is_integral_impl<long long int> : public true_type {}; #endif template <class _Tp> struct _is_integral : public _is_integral_impl<_Tp> {}; template<> struct _is_integral<char16_t> : public true_type {}; template<> struct _is_integral<char32_t> : public true_type {}; template<> struct _is_integral<int64_t> : public true_type {}; template<> struct _is_integral<uint64_t> : public true_type {}; } template <class _Tp> struct is_integral : public detail::_is_integral<typename remove_cv<_Tp>::type> { };
The interesting fact is that in some older compilers, these C-shnye "big" types are not an integral constant . What can be understood and even forgive, since these types are non-standard for C ++ up to 11 standards, and generally they should not be there. But what is difficult to understand is that these types in the newest C ++ creative compiler Embarcadero (Embarcadero C ++ Builder), which C ++ 11 supposedly supports, are still not an integral constant in their 32-bit builds (like 20 years ago , then it was Borland still true). Apparently because of this, including, most of the standard C ++ 11 library is missing in these 32-bit assemblies (#include the ratio? Chrono? You will manage). Embarcadero seems to have decided to force the onset of the 64-bit era with the motto: “Do you want a C ++ 11 or newer standard? Build a 64-bit program (and only clang, our compiler cannot)! ”.
template <bool, class _Tp = detail::void_type> struct enable_if { }; template <class _Tp> struct enable_if<true, _Tp> { typedef _Tp type; }; template<class, class> struct is_same : public false_type { }; template<class _Tp> struct is_same<_Tp, _Tp> : public true_type//specialization { }; template <class _Tp> struct is_const : public false_type { }; template <class _Tp> struct is_const<const _Tp> : public true_type { }; template <class _Tp> struct is_const<const volatile _Tp> : public true_type { }; /// is_volatile template<class> struct is_volatile : public false_type { }; template<class _Tp> struct is_volatile<volatile _Tp> : public true_type { }; template<class _Tp> struct is_volatile<const volatile _Tp> : public true_type { };
namespace detail { template<bool> struct _sign_unsign_chooser; template<class _Tp> struct _signed_comparer { static const bool value = _Tp(-1) < _Tp(0); }; template<class _Tp> struct _unsigned_comparer { static const bool value = _Tp(0) < _Tp(-1); }; template<bool Val> struct _cat_base : integral_constant<bool, Val> { // base class for type predicates }; template<> struct _sign_unsign_chooser<true>//integral { template<class _Tp> struct _signed : public _cat_base<_signed_comparer<typename remove_cv<_Tp>::type>::value> { }; template<class _Tp> struct _unsigned : public _cat_base<_unsigned_comparer<typename remove_cv<_Tp>::type>::value> { }; }; template<> struct _sign_unsign_chooser<false>//floating point { template<class _Tp> struct _signed : public is_floating_point<_Tp> { }; template<class _Tp> struct _unsigned : public false_type { }; }; } template<class T> struct is_signed { // determine whether T is a signed type static const bool value = detail::_sign_unsign_chooser<is_integral<T>::value>::template _signed<T>::value; typedef const bool value_type; typedef integral_constant<bool, is_signed::value == bool(true)> type; operator value_type() const { // return stored value return (value); } value_type operator()() const { // return stored value return (value); } }; template<class T> struct is_unsigned { // determine whether T is an unsigned type static const bool value = detail::_sign_unsign_chooser<is_integral<T>::value>::template _unsigned<T>::value; typedef const bool value_type; typedef integral_constant<bool, is_unsigned::value == bool(true)> type; operator value_type() const { // return stored value return (value); } value_type operator()() const { // return stored value return (value); } };
namespace detail { template <class _Tp> struct _alignment_of_trick { char c; _Tp t; _alignment_of_trick(); }; template <unsigned A, unsigned S> struct _alignment_logic_helper { static const std::size_t value = A < S ? A : S; }; template <unsigned A> struct _alignment_logic_helper<A, 0> { static const std::size_t value = A; }; template <unsigned S> struct _alignment_logic_helper<0, S> { static const std::size_t value = S; }; template< class _Tp > struct _alignment_of_impl { #if _MSC_VER > 1400 // // With MSVC both the build in __alignof operator // and following logic gets things wrong from time to time // Using a combination of the two seems to make the most of a bad job: // static const std::size_t value = (_alignment_logic_helper< sizeof(_alignment_of_trick<_Tp>) - sizeof(_Tp), __alignof(_Tp) >::value); #else static const std::size_t value = (_alignment_logic_helper< sizeof(_alignment_of_trick<_Tp>) - sizeof(_Tp), sizeof(_Tp) >::value); #endif typedef integral_constant<std::size_t, std::size_t(_alignment_of_impl::value)> type; private: typedef intern::type_traits_asserts check; typedef typename check::alignment_of_type_can_not_be_zero_assert< _alignment_of_impl::value != 0 >:: alignment_of_type_can_not_be_zero_assert_failed check1; // if you are there means aligment of type passed can not be calculated or compiler can not handle this situation (sorry, nothing can be done there) }; // borland compilers seem to be unable to handle long double correctly, so this will do the trick: struct _long_double_wrapper{ long double value; }; } template <class _Tp> struct alignment_of: public detail::_alignment_of_impl<_Tp>::type {}; template <class _Tp> struct alignment_of<_Tp&>: public alignment_of<_Tp*> {}; template<> struct alignment_of<long double>: public alignment_of<detail::_long_double_wrapper> {};
Here Microsoft again excelled with their Visual Studio, which even with a built-in nonstandard __alignof build-in macro still produces incorrect results when using it.Explanation from boostVisual C ++ users should not note that MSVC has varying definitions of "alignment". For example consider the following code:
typedef long long align_t; assert(boost::alignment_of<align_t>::value % 8 == 0); align_t a; assert(((std::uintptr_t)&a % 8) == 0); char c = 0; align_t a1; assert(((std::uintptr_t)&a1 % 8) == 0);
In this code, even though the boost has been set up, it can be a 32-bit build because it is not aligned with the 8-byte alignment. Note that we used the MSVC intrinsic __alignof in place of the boost :: we would still get the same result. In fact, for MSVC alignment requirements and
namespace intern { // since we have no static_assert in pre-C++11 we just compile-time assert this way: struct type_traits_asserts { template<bool> struct make_signed_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert; template<bool> struct make_unsigned_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert; template<bool> struct not_allowed_arithmetic_type_assert; template<bool> struct alignment_of_type_can_not_be_zero_assert; }; template<> struct type_traits_asserts::make_signed_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert<true> { typedef bool make_signed_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert_failed; }; template<> struct type_traits_asserts::make_unsigned_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert<true> { typedef bool make_unsigned_template_require_that_type_shall_be_a_possibly_cv_qualified_but_integral_type_assert_failed; }; template<> struct type_traits_asserts::not_allowed_arithmetic_type_assert<true> { typedef bool not_allowed_arithmetic_type_assert_failed; }; template<> struct type_traits_asserts::alignment_of_type_can_not_be_zero_assert<true> { typedef bool alignment_of_type_can_not_be_zero_assert_failed; }; }
Source: https://habr.com/ru/post/417949/
All Articles