From 3b6ba46f17698535418cbc6d3cdd006911a89e26 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 7 Jul 2012 14:58:46 +0900 Subject: [PATCH] fix math/comparison.hpp --- sprout/math.hpp | 7 +++ sprout/math/atan2.hpp | 6 +- sprout/math/compare.hpp | 25 +++------ sprout/math/equal_to.hpp | 39 ++++++++----- sprout/math/fdim.hpp | 6 +- sprout/math/float_promote.hpp | 50 ----------------- sprout/math/fma.hpp | 6 +- sprout/math/fmax.hpp | 6 +- sprout/math/fmin.hpp | 6 +- sprout/math/greater.hpp | 57 ++++++++++++++----- sprout/math/greater_equal.hpp | 59 +++++++++++++++----- sprout/math/hypot.hpp | 10 ++-- sprout/math/less.hpp | 57 ++++++++++++++----- sprout/math/less_equal.hpp | 59 +++++++++++++++----- sprout/math/not_equal_to.hpp | 7 +-- sprout/math/pow.hpp | 6 +- sprout/type_traits.hpp | 2 + sprout/type_traits/arithmetic_promote.hpp | 56 +++++++++++++++++++ sprout/type_traits/float_promote.hpp | 67 +++++++++++++++++++++++ sprout/utility/as_const.hpp | 15 +++-- sprout/utility/as_lvalue.hpp | 6 +- sprout/utility/forward.hpp | 6 +- sprout/utility/move.hpp | 6 +- 23 files changed, 389 insertions(+), 175 deletions(-) create mode 100644 sprout/math.hpp delete mode 100644 sprout/math/float_promote.hpp create mode 100644 sprout/type_traits/arithmetic_promote.hpp create mode 100644 sprout/type_traits/float_promote.hpp diff --git a/sprout/math.hpp b/sprout/math.hpp new file mode 100644 index 00000000..b6ea1eba --- /dev/null +++ b/sprout/math.hpp @@ -0,0 +1,7 @@ +#ifndef SPROUT_MATH_HPP +#define SPROUT_MATH_HPP + +#include +#include + +#endif // #ifndef SPROUT_MATH_HPP diff --git a/sprout/math/atan2.hpp b/sprout/math/atan2.hpp index 7e15766f..928da281 100644 --- a/sprout/math/atan2.hpp +++ b/sprout/math/atan2.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -31,9 +31,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type atan2(ArithmeticType1 y, ArithmeticType2 x) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::atan2(static_cast(y), static_cast(x)); } } // namespace detail diff --git a/sprout/math/compare.hpp b/sprout/math/compare.hpp index 18dc119e..88fe115a 100644 --- a/sprout/math/compare.hpp +++ b/sprout/math/compare.hpp @@ -4,33 +4,24 @@ #include #include #include -#include +#include #include namespace sprout { namespace math { - namespace detail { - template - inline SPROUT_CONSTEXPR int - compare_impl(T x, T y) { - return sprout::math::equal_to(x, y) ? 0 - : x < y ? -1 - : 1 - ; - } - } // namespace detail // // compare // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR int - compare(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::compare_impl(x, y); + compare(T x, U y) { + return sprout::math::equal_to(x, y) ? 0 + : sprout::math::less(x, y) ? -1 + : 1 + ; } } // namespace math } // namespace sprout diff --git a/sprout/math/equal_to.hpp b/sprout/math/equal_to.hpp index 86564ce4..a3e4efe0 100644 --- a/sprout/math/equal_to.hpp +++ b/sprout/math/equal_to.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -18,12 +18,9 @@ namespace sprout { return sprout::max(sprout::max(x, y), z); } - template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler - > + template inline SPROUT_CONSTEXPR bool - equal_to(FloatType x, FloatType y) { + equal_to_impl(FloatType x, FloatType y) { return x == y || sprout::abs(x - y) <= std::numeric_limits::epsilon() * sprout::math::detail::max3(std::abs(x), std::abs(y), FloatType(1.0)) @@ -31,11 +28,25 @@ namespace sprout { } template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename FloatType1, typename FloatType2, + typename sprout::enabler_if< + std::is_floating_point::type>::value + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - equal_to(IntType x, IntType y) { + equal_to(FloatType1 x, FloatType2 y) { + typedef typename sprout::arithmetic_promote::type type; + return sprout::math::detail::equal_to_impl(x, y); + } + + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + equal_to(IntType1 x, IntType2 y) { return x == y; } } // namespace detail @@ -43,14 +54,12 @@ namespace sprout { // equal_to // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - equal_to(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::equal_to(x, y); + equal_to(T x, U y) { + return sprout::math::detail::equal_to(x, y); } } // namespace math } // namespace sprout diff --git a/sprout/math/fdim.hpp b/sprout/math/fdim.hpp index 05da8798..cfb145be 100644 --- a/sprout/math/fdim.hpp +++ b/sprout/math/fdim.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -26,9 +26,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type fdim(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::fdim(static_cast(x), static_cast(y)); } } // namespace detail diff --git a/sprout/math/float_promote.hpp b/sprout/math/float_promote.hpp deleted file mode 100644 index dc880706..00000000 --- a/sprout/math/float_promote.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef SPROUT_MATH_FLOAT_PROMOTE_HPP -#define SPROUT_MATH_FLOAT_PROMOTE_HPP - -#include -#include - -namespace sprout { - namespace math { - namespace detail { - template - struct float_promote2 - : public std::conditional< - (std::is_same::value || std::is_same::value), - std::common_type, - typename std::conditional< - (std::is_same::value && std::is_same::value), - float, - double - > - >::type - { - static_assert(std::is_arithmetic::value, "float_promote requires arithmetic type."); - }; - - template - struct float_promote_impl - : public sprout::math::detail::float_promote_impl< - typename sprout::math::detail::float_promote2::type, - Tail... - > - {}; - template - struct float_promote_impl - : public sprout::math::detail::float_promote2 - {}; - } // namespace detail - - // - // float_promote - // - template - struct float_promote - : public sprout::math::detail::float_promote_impl< - float, typename std::remove_cv::type... - > - {}; - } // namespace math -} // namespace sprout - -#endif // #ifndef SPROUT_MATH_FLOAT_PROMOTE_HPP diff --git a/sprout/math/fma.hpp b/sprout/math/fma.hpp index 53eb990e..d9b4f15f 100644 --- a/sprout/math/fma.hpp +++ b/sprout/math/fma.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -29,11 +29,11 @@ namespace sprout { && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote< + inline SPROUT_CONSTEXPR typename sprout::float_promote< ArithmeticType1, ArithmeticType2, ArithmeticType3 >::type fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) { - typedef typename sprout::math::float_promote< + typedef typename sprout::float_promote< ArithmeticType1, ArithmeticType2, ArithmeticType3 >::type type; return sprout::math::detail::fma(static_cast(x), static_cast(y), static_cast(z)); diff --git a/sprout/math/fmax.hpp b/sprout/math/fmax.hpp index 1e3faa5e..e7768aa1 100644 --- a/sprout/math/fmax.hpp +++ b/sprout/math/fmax.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -26,9 +26,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type fmax(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::fmax(static_cast(x), static_cast(y)); } } // namespace detail diff --git a/sprout/math/fmin.hpp b/sprout/math/fmin.hpp index 85f52476..a151bf81 100644 --- a/sprout/math/fmin.hpp +++ b/sprout/math/fmin.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -26,9 +26,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type fmin(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::fmin(static_cast(x), static_cast(y)); } } // namespace detail diff --git a/sprout/math/greater.hpp b/sprout/math/greater.hpp index a49774c2..267a76c5 100644 --- a/sprout/math/greater.hpp +++ b/sprout/math/greater.hpp @@ -4,42 +4,73 @@ #include #include #include -#include +#include #include namespace sprout { namespace math { namespace detail { template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename FloatType1, typename FloatType2, + typename sprout::enabler_if< + std::is_floating_point::type>::value + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater(FloatType x, FloatType y) { + greater(FloatType1 x, FloatType2 y) { return sprout::math::not_equal_to(x, y) && x > y; } template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && (std::is_unsigned::value == std::is_unsigned::value) + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater(IntType x, IntType y) { + greater(IntType1 x, IntType2 y) { return x > y; } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_signed::value && std::is_unsigned::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + greater(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return x < 0 ? false + : static_cast(x) > static_cast(y) + ; + } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_unsigned::value && std::is_signed::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + greater(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return y < 0 ? true + : static_cast(x) > static_cast(y) + ; + } } // namespace detail // // greater // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::greater(x, y); + greater(T x, U y) { + return sprout::math::detail::greater(x, y); } } // namespace math } // namespace sprout diff --git a/sprout/math/greater_equal.hpp b/sprout/math/greater_equal.hpp index 8c83996f..05f5201a 100644 --- a/sprout/math/greater_equal.hpp +++ b/sprout/math/greater_equal.hpp @@ -4,42 +4,73 @@ #include #include #include -#include +#include #include namespace sprout { namespace math { namespace detail { template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename FloatType1, typename FloatType2, + typename sprout::enabler_if< + std::is_floating_point::type>::value + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater_equal(FloatType x, FloatType y) { + greater_equal_equal(FloatType1 x, FloatType2 y) { return sprout::math::equal_to(x, y) || x > y; } template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && (std::is_unsigned::value == std::is_unsigned::value) + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater_equal(IntType x, IntType y) { + greater_equal(IntType1 x, IntType2 y) { return x >= y; } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_signed::value && std::is_unsigned::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + greater_equal(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return x < 0 ? false + : static_cast(x) >= static_cast(y) + ; + } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_unsigned::value && std::is_signed::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + greater_equal(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return y < 0 ? true + : static_cast(x) >= static_cast(y) + ; + } } // namespace detail // - // greater_equal + // greater_equal_equal // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - greater_equal(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::greater_equal(x, y); + greater_equal(T x, U y) { + return sprout::math::detail::greater_equal(x, y); } } // namespace math } // namespace sprout diff --git a/sprout/math/hypot.hpp b/sprout/math/hypot.hpp index 0068166f..5b2645bc 100644 --- a/sprout/math/hypot.hpp +++ b/sprout/math/hypot.hpp @@ -3,10 +3,10 @@ #include #include -#include -#include -#include +#include #include +#include +#include namespace sprout { namespace math { @@ -27,9 +27,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type hypot(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::hypot(static_cast(x), static_cast(y)); } } // namespace detail diff --git a/sprout/math/less.hpp b/sprout/math/less.hpp index f4108331..647180d8 100644 --- a/sprout/math/less.hpp +++ b/sprout/math/less.hpp @@ -4,42 +4,73 @@ #include #include #include -#include +#include #include namespace sprout { namespace math { namespace detail { template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename FloatType1, typename FloatType2, + typename sprout::enabler_if< + std::is_floating_point::type>::value + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less(FloatType x, FloatType y) { + less(FloatType1 x, FloatType2 y) { return sprout::math::not_equal_to(x, y) && x < y; } template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && (std::is_unsigned::value == std::is_unsigned::value) + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less(IntType x, IntType y) { + less(IntType1 x, IntType2 y) { return x < y; } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_signed::value && std::is_unsigned::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + less(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return x < 0 ? true + : static_cast(x) < static_cast(y) + ; + } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_unsigned::value && std::is_signed::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + less(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return y < 0 ? false + : static_cast(x) < static_cast(y) + ; + } } // namespace detail // // less // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::less(x, y); + less(T x, U y) { + return sprout::math::detail::less(x, y); } } // namespace math } // namespace sprout diff --git a/sprout/math/less_equal.hpp b/sprout/math/less_equal.hpp index e7418fd9..9599885d 100644 --- a/sprout/math/less_equal.hpp +++ b/sprout/math/less_equal.hpp @@ -4,42 +4,73 @@ #include #include #include -#include +#include #include namespace sprout { namespace math { namespace detail { template< - typename FloatType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename FloatType1, typename FloatType2, + typename sprout::enabler_if< + std::is_floating_point::type>::value + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less_equal(FloatType x, FloatType y) { - return sprout::math::equal_to(x, y) || x < y; + less_equal(FloatType1 x, FloatType2 y) { + return sprout::math::not_equal_to(x, y) || x < y; } template< - typename IntType, - typename sprout::enabler_if::value>::type = sprout::enabler + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && (std::is_unsigned::value == std::is_unsigned::value) + >::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less_equal(IntType x, IntType y) { + less_equal(IntType1 x, IntType2 y) { return x <= y; } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_signed::value && std::is_unsigned::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + less_equal(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return x < 0 ? true + : static_cast(x) <= static_cast(y) + ; + } + template< + typename IntType1, typename IntType2, + typename sprout::enabler_if< + std::is_integral::type>::value + && std::is_unsigned::value && std::is_signed::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + less_equal(IntType1 x, IntType2 y) { + typedef typename std::make_unsigned::type>::type type; + return y < 0 ? false + : static_cast(x) <= static_cast(y) + ; + } } // namespace detail // // less_equal // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - less_equal(T1 x, T2 y) { - typedef typename sprout::math::float_promote::type promoted; - return sprout::math::detail::less_equal(x, y); + less_equal(T x, U y) { + return sprout::math::detail::less_equal(x, y); } } // namespace math } // namespace sprout diff --git a/sprout/math/not_equal_to.hpp b/sprout/math/not_equal_to.hpp index 60037abb..d8db2ceb 100644 --- a/sprout/math/not_equal_to.hpp +++ b/sprout/math/not_equal_to.hpp @@ -12,12 +12,11 @@ namespace sprout { // not_equal_to // template< - typename T1, - typename T2, - typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler + typename T, typename U, + typename sprout::enabler_if::value && std::is_arithmetic::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR bool - not_equal_to(T1 x, T2 y) { + not_equal_to(T x, U y) { return !sprout::math::equal_to(x, y); } } // namespace math diff --git a/sprout/math/pow.hpp b/sprout/math/pow.hpp index 1894b323..216871ac 100644 --- a/sprout/math/pow.hpp +++ b/sprout/math/pow.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -31,9 +31,9 @@ namespace sprout { std::is_arithmetic::value && std::is_arithmetic::value >::type = sprout::enabler > - inline SPROUT_CONSTEXPR typename sprout::math::float_promote::type + inline SPROUT_CONSTEXPR typename sprout::float_promote::type pow(ArithmeticType1 x, ArithmeticType2 y) { - typedef typename sprout::math::float_promote::type type; + typedef typename sprout::float_promote::type type; return sprout::math::detail::pow(static_cast(x), static_cast(y)); } } // namespace detail diff --git a/sprout/type_traits.hpp b/sprout/type_traits.hpp index c3f54d4e..88d26a6b 100644 --- a/sprout/type_traits.hpp +++ b/sprout/type_traits.hpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/sprout/type_traits/arithmetic_promote.hpp b/sprout/type_traits/arithmetic_promote.hpp new file mode 100644 index 00000000..154f1f17 --- /dev/null +++ b/sprout/type_traits/arithmetic_promote.hpp @@ -0,0 +1,56 @@ +#ifndef SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP +#define SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP + +#include +#include +#include + +namespace sprout { + namespace detail { + template + struct arithmetic_promote1 + : public std::common_type + { + static_assert( + std::is_arithmetic::value, + "arithmetic_promote requires arithmetic types." + ); + }; + + template + struct arithmetic_promote2 + : public std::decay() + std::declval())> + { + static_assert( + std::is_arithmetic::value && std::is_arithmetic::value, + "arithmetic_promote requires arithmetic types." + ); + }; + + template + struct arithmetic_promote_impl; + template + struct arithmetic_promote_impl + : public sprout::detail::arithmetic_promote_impl< + typename sprout::detail::arithmetic_promote2::type, + Tail... + > + {}; + template + struct arithmetic_promote_impl + : public sprout::detail::arithmetic_promote1 + {}; + } // namespace detail + + // + // arithmetic_promote + // + template + struct arithmetic_promote + : public sprout::detail::arithmetic_promote_impl< + typename std::remove_cv::type... + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP diff --git a/sprout/type_traits/float_promote.hpp b/sprout/type_traits/float_promote.hpp new file mode 100644 index 00000000..1c3dcedb --- /dev/null +++ b/sprout/type_traits/float_promote.hpp @@ -0,0 +1,67 @@ +#ifndef SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP +#define SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP + +#include +#include + +namespace sprout { + namespace detail { + template + struct float_promote1 + : public std::conditional< + std::is_floating_point::value, + std::common_type, + std::common_type + >::type + { + static_assert( + std::is_arithmetic::value, + "float_promote requires arithmetic type." + ); + }; + + template + struct float_promote2 + : public std::conditional< + (std::is_same::value || std::is_same::value), + std::common_type, + typename std::conditional< + (std::is_same::value && std::is_same::value), + float, + double + > + >::type + { + static_assert( + std::is_arithmetic::value && std::is_arithmetic::value, + "float_promote requires arithmetic type." + ); + }; + + template + struct float_promote_impl; + template + struct float_promote_impl + : public sprout::detail::float_promote_impl< + typename sprout::detail::float_promote2::type, + Tail... + > + {}; + template + struct float_promote_impl + : public sprout::detail::float_promote1 + {}; + } // namespace detail + + // + // float_promote + // + template + struct float_promote + : public sprout::detail::float_promote_impl< + typename std::remove_cv::type... + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP diff --git a/sprout/utility/as_const.hpp b/sprout/utility/as_const.hpp index 80bd470e..ea22dbc5 100644 --- a/sprout/utility/as_const.hpp +++ b/sprout/utility/as_const.hpp @@ -1,19 +1,22 @@ #ifndef SPROUT_UTILITY_AS_CONST_HPP #define SPROUT_UTILITY_AS_CONST_HPP +#include #include +#include namespace sprout { // // as_const // template - inline T const& as_const(T& t) { - return t; - } - template - inline SPROUT_CONSTEXPR T const& as_const(T const& t) { - return t; + inline SPROUT_CONSTEXPR typename std::conditional< + std::is_lvalue_reference::value, + typename std::remove_reference::type const&, + typename std::remove_reference::type const&& + >::type + as_const(T&& t) { + return sprout::forward(t); } } // namespace sprout diff --git a/sprout/utility/as_lvalue.hpp b/sprout/utility/as_lvalue.hpp index 7f316f12..05f234a3 100644 --- a/sprout/utility/as_lvalue.hpp +++ b/sprout/utility/as_lvalue.hpp @@ -8,11 +8,13 @@ namespace sprout { // as_lvalue // template - inline T& as_lvalue(T& t) { + inline SPROUT_CONSTEXPR T& + as_lvalue(T& t) { return t; } template - inline SPROUT_CONSTEXPR T const& as_lvalue(T const& t) { + inline SPROUT_CONSTEXPR T const& + as_lvalue(T const& t) { return t; } } // namespace sprout diff --git a/sprout/utility/forward.hpp b/sprout/utility/forward.hpp index f18e6f6a..4c178d2d 100644 --- a/sprout/utility/forward.hpp +++ b/sprout/utility/forward.hpp @@ -9,11 +9,13 @@ namespace sprout { // forward // template - inline SPROUT_CONSTEXPR T&& forward(typename std::remove_reference::type& t) SPROUT_NOEXCEPT { + inline SPROUT_CONSTEXPR T&& + forward(typename std::remove_reference::type& t) SPROUT_NOEXCEPT { return static_cast(t); } template - inline SPROUT_CONSTEXPR T&& forward(typename std::remove_reference::type&& t) SPROUT_NOEXCEPT = delete; + inline SPROUT_CONSTEXPR T&& + forward(typename std::remove_reference::type&& t) SPROUT_NOEXCEPT = delete; } // namespace sprout #endif // #ifndef SPROUT_UTILITY_FORWARD_HPP diff --git a/sprout/utility/move.hpp b/sprout/utility/move.hpp index 80f4817c..f28a07be 100644 --- a/sprout/utility/move.hpp +++ b/sprout/utility/move.hpp @@ -9,7 +9,8 @@ namespace sprout { // move // template - inline SPROUT_CONSTEXPR typename std::remove_reference::type&& move(T&& x) SPROUT_NOEXCEPT { + inline SPROUT_CONSTEXPR typename std::remove_reference::type&& + move(T&& x) SPROUT_NOEXCEPT { return static_cast::type&&>(x); } @@ -21,7 +22,8 @@ namespace sprout { !std::is_nothrow_move_constructible::value && std::is_copy_constructible::value, T const&, T&& - >::type move_if_noexcept(T& x) SPROUT_NOEXCEPT { + >::type + move_if_noexcept(T& x) SPROUT_NOEXCEPT { return sprout::move(x); } } // namespace sprout