From 196aa8dfbd9d2ba5f12bf7a21180b97300c1cd39 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Thu, 19 Jul 2012 19:17:25 +0900 Subject: [PATCH] fix sprout::tuples::get --- sprout/config/config.hpp | 2 + sprout/tuple/tuple/get.hpp | 115 ++++++++++++++++++++++++++++++++----- 2 files changed, 104 insertions(+), 13 deletions(-) diff --git a/sprout/config/config.hpp b/sprout/config/config.hpp index 4b50d643..24374ca2 100644 --- a/sprout/config/config.hpp +++ b/sprout/config/config.hpp @@ -26,9 +26,11 @@ #ifndef SPROUT_CONFIG_DISABLE_NOEXCEPT # define SPROUT_NOEXCEPT noexcept # define SPROUT_NOEXCEPT_EXPR(EXPR) noexcept(EXPR) +# define SPROUT_NOEXCEPT_EXPR_OR_DEFAULT(EXPR, C) noexcept(EXPR) #else // #ifndef SPROUT_CONFIG_DISABLE_NOEXCEPT # define SPROUT_NOEXCEPT # define SPROUT_NOEXCEPT_EXPR(EXPR) +# define SPROUT_NOEXCEPT_EXPR_OR_DEFAULT(EXPR, C) C #endif // #ifndef SPROUT_CONFIG_DISABLE_NOEXCEPT #ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES diff --git a/sprout/tuple/tuple/get.hpp b/sprout/tuple/tuple/get.hpp index 8b8897f1..69e304f1 100644 --- a/sprout/tuple/tuple/get.hpp +++ b/sprout/tuple/tuple/get.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -50,19 +51,6 @@ namespace sprout { : public sprout::tuples::tuple_element {}; - // - // get - // - template - inline SPROUT_CONSTEXPR auto - get(T&& t) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::get(sprout::forward(t)))) - -> decltype(std::get(sprout::forward(t))) - { - return std::get(sprout::forward(t)); - } - // - // get - // namespace detail { template inline SPROUT_CONSTEXPR typename std::add_lvalue_reference::type @@ -75,6 +63,9 @@ namespace sprout { return sprout::tuples::detail::tuple_impl::head(t); } } // namespace detail + // + // get + // template inline SPROUT_CONSTEXPR typename sprout::tuples::tuple_element >::type& get(sprout::tuples::tuple& t) SPROUT_NOEXCEPT { @@ -94,6 +85,104 @@ namespace sprout { } } // namespace tuples + namespace tuple_detail { + struct not_found_adl_get {}; + + template + sprout::tuple_detail::not_found_adl_get get(...); + + template + struct has_std_get_test { + public: + template< + typename U = T, + typename = decltype(std::get(std::declval())) + > + static std::true_type test(int); + static std::false_type test(...); + }; + template + struct has_std_get + : public decltype(sprout::tuple_detail::has_std_get_test::test(0)) + {}; + + template + struct has_adl_get_test { + public: + template< + typename U = T, + typename sprout::enabler_if< + !std::is_same(std::declval())), sprout::tuple_detail::not_found_adl_get>::value + && !sprout::tuple_detail::has_std_get::value + >::type = sprout::enabler + > + static std::true_type test(int); + static std::false_type test(...); + }; + template + struct has_adl_get + : public decltype(sprout::tuple_detail::has_adl_get_test::test(0)) + {}; + + template + struct noexcept_get; + template + struct noexcept_get::value>::type> + : public std::integral_constant(std::declval()), false)> + {}; + template + struct noexcept_get::value>::type> + : public std::integral_constant(std::declval()), false)> + {}; + + template + struct get_result; + template + struct get_result::value>::type> { + public: + typedef decltype(get(std::declval())) type; + }; + template + struct get_result::value>::type> { + public: + typedef decltype(std::get(std::declval())) type; + }; + + template< + std::size_t I, typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::tuple_detail::get_result::type + get_impl(T&& t) + SPROUT_NOEXCEPT_EXPR((sprout::tuple_detail::noexcept_get::value)) + { + return get(sprout::forward(t)); + } + template< + std::size_t I, typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::tuple_detail::get_result::type + get_impl(T&& t) + SPROUT_NOEXCEPT_EXPR((sprout::tuple_detail::noexcept_get::value)) + { + return std::get(sprout::forward(t)); + } + } // namespace tuple_detail + + namespace tuples { + // + // get + // + template + inline SPROUT_CONSTEXPR typename sprout::tuple_detail::get_result::type + get(T&& t) + SPROUT_NOEXCEPT_EXPR((sprout::tuple_detail::noexcept_get::value)) + { + return sprout::tuple_detail::get_impl(sprout::forward(t)); + } + } // namespace tuples + using sprout::tuples::tuple_size; using sprout::tuples::tuple_element; using sprout::tuples::get;