add type_traits is_invocable

This commit is contained in:
bolero-MURAKAMI 2017-09-19 20:01:44 +09:00
parent 2614c4e3f9
commit 8158baa39f
10 changed files with 287 additions and 34 deletions

View file

@ -0,0 +1,73 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_DETAIL_INVOKE_HPP
#define SPROUT_TYPE_TRAITS_DETAIL_INVOKE_HPP
#include <utility>
#include <sprout/config.hpp>
#include <sprout/type_traits/identity.hpp>
#include <sprout/type_traits/voider.hpp>
#include <sprout/detail/nil_base.hpp>
#include <sprout/utility/implicit_cast.hpp>
namespace sprout {
namespace detail {
template<typename F, typename... Args>
inline SPROUT_CONSTEXPR decltype(std::declval<F>()(std::declval<Args>()...))
invoke(F&&, Args&&...) SPROUT_NOEXCEPT_IF_EXPR(std::declval<F>()(std::declval<Args>()...));
template<typename Base, typename T, typename Derived>
inline SPROUT_CONSTEXPR decltype(std::declval<Derived>().*(std::declval<T Base::*>()))
invoke(T Base::*, Derived&&) SPROUT_NOEXCEPT_IF_EXPR(std::declval<Derived>().*(std::declval<T Base::*>()));
template<typename PMD, typename Pointer>
inline SPROUT_CONSTEXPR decltype((*std::declval<Pointer>()).*(std::declval<PMD>()))
invoke(PMD&&, Pointer&&) SPROUT_NOEXCEPT_IF_EXPR((*std::declval<Pointer>()).*(std::declval<PMD>()));
template<typename Base, typename T, typename Derived, typename... Args>
inline SPROUT_CONSTEXPR decltype((std::declval<Derived>().*(std::declval<T Base::*>()))(std::declval<Args>()...))
invoke(T Base::*, Derived&&, Args&&...) SPROUT_NOEXCEPT_IF_EXPR((std::declval<Derived>().*(std::declval<T Base::*>()))(std::declval<Args>()...));
template<typename PMF, typename Pointer, typename... Args>
inline SPROUT_CONSTEXPR decltype(((*std::declval<Pointer>()).*(std::declval<PMF>()))(std::declval<Args>()...))
invoke(PMF&& pmf, Pointer&& ptr, Args&&... args) SPROUT_NOEXCEPT_IF_EXPR(((*std::declval<Pointer>()).*(std::declval<PMF>()))(std::declval<Args>()...));
template<typename R, typename F, typename... Args>
inline SPROUT_CONSTEXPR R
invoke(F&&, Args&&...) SPROUT_NOEXCEPT_IF_EXPR(R(std::declval<F>()(std::declval<Args>()...)));
template<typename R, typename Base, typename T, typename Derived>
inline SPROUT_CONSTEXPR decltype(R(std::declval<Derived>().*(std::declval<T Base::*>())))
invoke(T Base::*, Derived&&) SPROUT_NOEXCEPT_IF_EXPR(R(std::declval<Derived>().*(std::declval<T Base::*>())));
template<typename R, typename PMD, typename Pointer>
inline SPROUT_CONSTEXPR decltype(R((*std::declval<Pointer>()).*(std::declval<PMD>())))
invoke(PMD&&, Pointer&&) SPROUT_NOEXCEPT_IF_EXPR(R((*std::declval<Pointer>()).*(std::declval<PMD>())));
template<typename R, typename Base, typename T, typename Derived, typename... Args>
inline SPROUT_CONSTEXPR decltype(R((std::declval<Derived>().*(std::declval<T Base::*>()))(std::declval<Args>()...)))
invoke(T Base::*, Derived&&, Args&&...) SPROUT_NOEXCEPT_IF_EXPR(R((std::declval<Derived>().*(std::declval<T Base::*>()))(std::declval<Args>()...)));
template<typename R, typename PMF, typename Pointer, typename... Args>
inline SPROUT_CONSTEXPR decltype(R(((*std::declval<Pointer>()).*(std::declval<PMF>()))(std::declval<Args>()...)))
invoke(PMF&& pmf, Pointer&& ptr, Args&&... args) SPROUT_NOEXCEPT_IF_EXPR(R(((*std::declval<Pointer>()).*(std::declval<PMF>()))(std::declval<Args>()...)));
} // namespace detail
namespace detail {
template<typename Void, typename F, typename... Args>
struct invoke_result
: public sprout::detail::nil_base
{};
template<typename F, typename... Args>
struct invoke_result<typename sprout::voider<decltype(sprout::detail::invoke(std::declval<F>(), std::declval<Args>()...))>::type, F, Args...>
: public sprout::identity<decltype(sprout::detail::invoke(std::declval<F>(), std::declval<Args>()...))>
{};
} // namespace detail
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_TRAITS_DETAIL_INVOKE_HPP

View file

@ -9,7 +9,7 @@
#define SPROUT_TYPE_TRAITS_INVOKE_RESULT_HPP
#include <sprout/config.hpp>
#include <sprout/type_traits/result_of.hpp>
#include <sprout/type_traits/detail/invoke.hpp>
namespace sprout {
//

View file

@ -0,0 +1,43 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_IS_INVOCABLE_HPP
#define SPROUT_TYPE_TRAITS_IS_INVOCABLE_HPP
#include <sprout/config.hpp>
#include <sprout/type_traits/integral_constant.hpp>
#include <sprout/type_traits/invoke_result.hpp>
#include <sprout/type_traits/voider.hpp>
namespace sprout {
//
// is_invocable
//
namespace detail {
template<typename Result, typename = void>
struct is_invocable_impl
: public sprout::false_type
{};
template<typename Result>
struct is_invocable_impl<Result, typename sprout::voider<typename Result::type>::type>
: public sprout::true_type
{};
} // namespace detail
template<typename F, typename... Args>
struct is_invocable
: public sprout::detail::is_invocable_impl<
sprout::invoke_result<F, Args...>
>::type
{};
#if SPROUT_USE_VARIABLE_TEMPLATES
template<typename F, typename... Args>
SPROUT_STATIC_CONSTEXPR bool is_invocable_v = sprout::is_invocable<F, Args...>::value;
#endif // #if SPROUT_USE_VARIABLE_TEMPLATES
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_TRAITS_IS_INVOCABLE_HPP

View file

@ -0,0 +1,46 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_IS_INVOCABLE_R_HPP
#define SPROUT_TYPE_TRAITS_IS_INVOCABLE_R_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/integral_constant.hpp>
#include <sprout/type_traits/invoke_result.hpp>
#include <sprout/type_traits/voider.hpp>
namespace sprout {
//
// is_invocable_r
//
namespace detail {
template<typename R, typename Result, typename = void>
struct is_invocable_r_impl
: public sprout::false_type
{};
template<typename R, typename Result>
struct is_invocable_r_impl<R, Result, typename sprout::voider<typename Result::type>::type>
: public sprout::bool_constant<
std::is_void<R>::value || std::is_convertible<typename Result::type, R>::value
>
{};
} // namespace detail
template<typename R, typename F, typename... Args>
struct is_invocable_r
: public sprout::detail::is_invocable_r_impl<
R, sprout::invoke_result<F, Args...>
>::type
{};
#if SPROUT_USE_VARIABLE_TEMPLATES
template<typename R, typename F, typename... Args>
SPROUT_STATIC_CONSTEXPR bool is_invocable_r_v = sprout::is_invocable_r<R, F, Args...>::value;
#endif // #if SPROUT_USE_VARIABLE_TEMPLATES
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_TRAITS_IS_INVOCABLE_R_HPP

View file

@ -0,0 +1,45 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP
#define SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP
#include <sprout/config.hpp>
#include <sprout/type_traits/integral_constant.hpp>
#include <sprout/type_traits/invoke_result.hpp>
#include <sprout/type_traits/detail/invoke.hpp>
namespace sprout {
//
// is_nothrow_invocable
//
namespace detail {
template<bool Cond, typename F, typename... Args>
struct is_nothrow_invocable_impl
: public sprout::false_type
{};
template<typename F, typename... Args>
struct is_nothrow_invocable_impl<true, F, Args...>
: public sprout::bool_constant<
SPROUT_NOEXCEPT_EXPR(sprout::detail::invoke(std::declval<F>(), std::declval<Args>()...))
>
{};
} // namespace detail
template<typename F, typename... Args>
struct is_nothrow_invocable
: public sprout::detail::is_nothrow_invocable_impl<
sprout::is_invocable<F, Args...>::value, F, Args...
>::type
{};
#if SPROUT_USE_VARIABLE_TEMPLATES
template<typename F, typename... Args>
SPROUT_STATIC_CONSTEXPR bool is_nothrow_invocable_v = sprout::is_nothrow_invocable<F, Args...>::value;
#endif // #if SPROUT_USE_VARIABLE_TEMPLATES
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_HPP

View file

@ -0,0 +1,47 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_R_HPP
#define SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_R_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/integral_constant.hpp>
#include <sprout/type_traits/invoke_result.hpp>
#include <sprout/type_traits/voider.hpp>
#include <sprout/type_traits/detail/invoke.hpp>
namespace sprout {
//
// is_nothrow_invocable_r
//
namespace detail {
template<bool Cond, typename R, typename F, typename... Args>
struct is_nothrow_invocable_r_impl
: public sprout::false_type
{};
template<typename R, typename F, typename... Args>
struct is_nothrow_invocable_r_impl<true, R, F, Args...>
: public sprout::bool_constant<
SPROUT_NOEXCEPT_EXPR(sprout::detail::invoke<R>(std::declval<F>(), std::declval<Args>()...))
>
{};
} // namespace detail
template<typename R, typename F, typename... Args>
struct is_nothrow_invocable_r
: public sprout::detail::is_nothrow_invocable_r_impl<
sprout::is_invocable_r<R, F, Args...>::value, R, F, Args...
>::type
{};
#if SPROUT_USE_VARIABLE_TEMPLATES
template<typename R, typename F, typename... Args>
SPROUT_STATIC_CONSTEXPR bool is_nothrow_invocable_r_v = sprout::is_nothrow_invocable_r<R, F, Args...>::value;
#endif // #if SPROUT_USE_VARIABLE_TEMPLATES
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_TRAITS_IS_NOTHROW_INVOCABLE_R_HPP

View file

@ -13,6 +13,10 @@
#include <sprout/type_traits/is_same.hpp>
#include <sprout/type_traits/is_base_of.hpp>
#include <sprout/type_traits/is_convertible.hpp>
#include <sprout/type_traits/is_invocable.hpp>
#include <sprout/type_traits/is_invocable_r.hpp>
#include <sprout/type_traits/is_nothrow_invocable.hpp>
#include <sprout/type_traits/is_nothrow_invocable_r.hpp>
#include <sprout/type_traits/is_const_cast_convertible.hpp>
#include <sprout/type_traits/is_convert_constructible.hpp>

View file

@ -8,42 +8,10 @@
#ifndef SPROUT_TYPE_TRAITS_RESULT_OF_HPP
#define SPROUT_TYPE_TRAITS_RESULT_OF_HPP
#include <utility>
#include <sprout/config.hpp>
#include <sprout/type_traits/identity.hpp>
#include <sprout/type_traits/detail/invoke.hpp>
namespace sprout {
namespace detail {
template<typename F, typename... Args>
inline SPROUT_CONSTEXPR decltype(std::declval<F>()(std::declval<Args>()...))
invoke(F&&, Args&&...);
template<typename Base, typename T, typename Derived>
inline SPROUT_CONSTEXPR decltype(std::declval<Derived>().*(std::declval<T Base::*>()))
invoke(T Base::*, Derived&&);
template<typename PMD, typename Pointer>
inline SPROUT_CONSTEXPR decltype((*std::declval<Pointer>()).*(std::declval<PMD>()))
invoke(PMD&&, Pointer&&);
template<typename Base, typename T, typename Derived, typename... Args>
inline SPROUT_CONSTEXPR decltype((std::declval<Derived>().*(std::declval<T Base::*>()))(std::declval<Args>()...))
invoke(T Base::*, Derived&&, Args&&...);
template<typename PMF, typename Pointer, typename... Args>
inline SPROUT_CONSTEXPR decltype(((*std::declval<Pointer>()).*(std::declval<PMF>()))(std::declval<Args>()...))
invoke(PMF&& pmf, Pointer&& ptr, Args&&... args);
} // namespace detail
namespace detail {
template<typename Void, typename, typename...>
struct invoke_result {};
template<typename F, typename...Args>
struct invoke_result<decltype(void(sprout::detail::invoke(std::declval<F>(), std::declval<Args>()...))), F, Args...>
: public sprout::identity<decltype(sprout::detail::invoke(std::declval<F>(), std::declval<Args>()...))>
{};
} // namespace detail
//
// result_of
//

View file

@ -0,0 +1,14 @@
/*=============================================================================
Copyright (c) 2011-2017 Bolero MURAKAMI
https://github.com/bolero-MURAKAMI/Sprout
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef SPROUT_TYPE_TRAITS_VOID_T_HPP
#define SPROUT_TYPE_TRAITS_VOID_T_HPP
#include <sprout/config.hpp>
#include <sprout/type_traits/voider.hpp>
#endif // #ifndef SPROUT_TYPE_TRAITS_VOID_T_HPP

View file

@ -15,6 +15,8 @@
#include <iostream>
#include <iomanip>
#include <sprout/config.hpp>
#include <sprout/preprocessor/config.hpp>
#include <sprout/preprocessor/stringize.hpp>
#include <sprout/container.hpp>
#include <sprout/detail/io/ios_state.hpp>
#include <testspr/typeinfo.hpp>
@ -181,4 +183,15 @@ namespace testspr {
}
} // namespace testspr
//
// TESTSPR_PRINT_EXPR
//
#if SPROUT_PP_VARIADICS
# define TESTSPR_PRINT_EXPR(...) \
::testspr::print_ln(SPROUT_PP_STRINGIZE((__VA_ARGS__)), " => ", __VA_ARGS__)
#else
# define TESTSPR_PRINT_EXPR(EXPR) \
::testspr::print_ln(SPROUT_PP_STRINGIZE((EXPR)), " => ", EXPR)
#endif
#endif // #ifndef TESTSPR_PRINT_HPP