Loading src/sled/exec/detail/invoke_result.h +182 −153 Original line number Diff line number Diff line Loading @@ -18,13 +18,15 @@ namespace detail { #define EGGS_FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__) /////////////////////////////////////////////////////////////////////////// template<typename C, typename T, bool Ref, bool RefWrapper, bool IsFunction = std::is_function<T>::value> template <typename C, typename T, bool Ref, bool RefWrapper, bool IsFunction = std::is_function<T>::value> struct invoke_mem_ptr; // when `pm` is a pointer to member of a class `C` and // `is_base_of_v<C, remove_reference_t<T>>` is `true`; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -32,14 +34,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/f #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept(EGGS_FWD(t1).*pm)) -> decltype(EGGS_FWD(t1).*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept(EGGS_FWD(t1).*pm)) -> decltype(EGGS_FWD(t1).*pm) { return EGGS_FWD(t1).*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -47,9 +50,9 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/t #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...))) -> decltype((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...))) -> decltype((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...)) { return (EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...); } }; Loading @@ -57,7 +60,8 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/t // when `pm` is a pointer to member of a class `C` and // `remove_cvref_t<T>` is a specialization of `reference_wrapper`; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -65,14 +69,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/f #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept(t1.get().*pm)) -> decltype(t1.get().*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept(t1.get().*pm)) -> decltype(t1.get().*pm) { return t1.get().*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -80,9 +85,9 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/t #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((t1.get().*pm)(EGGS_FWD(tn)...))) -> decltype((t1.get().*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((t1.get().*pm)(EGGS_FWD(tn)...))) -> decltype((t1.get().*pm)(EGGS_FWD(tn)...)) { return (t1.get().*pm)(EGGS_FWD(tn)...); } }; Loading @@ -90,7 +95,8 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/t // when `pm` is a pointer to member of a class `C` and `T` does not // satisfy the previous two items; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -98,14 +104,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/ #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept((*EGGS_FWD(t1)).*pm)) -> decltype((*EGGS_FWD(t1)).*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept((*EGGS_FWD(t1)).*pm)) -> decltype((*EGGS_FWD(t1)).*pm) { return (*EGGS_FWD(t1)).*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -113,26 +120,25 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/ #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...))) -> decltype(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...))) -> decltype(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...)) { return ((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...); } }; /////////////////////////////////////////////////////////////////////////// template<typename F> auto invoke(F &&, ...) -> F &&; template <typename F> auto invoke(F &&, ...) -> F &&; template <typename T, typename C, typename T1> auto invoke(T C::*, T1 const &, ...) -> invoke_mem_ptr<C, T, auto invoke(T C::*, T1 const &, ...) -> invoke_mem_ptr<C, T, /*Ref=*/std::is_base_of<C, T1>::value, /*RefWrapper=*/false>; template <typename T, typename C, typename X> auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, T, auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true>; Loading @@ -141,11 +147,16 @@ auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, //! - _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. #if __cplusplus > 201703L // C++20: P0306 #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F __VA_OPT__(, ) __VA_ARGS__))>(F)(__VA_ARGS__)) (static_cast<decltype(::eggs::detail::invoke( \ F __VA_OPT__(, ) __VA_ARGS__))>(F)(__VA_ARGS__)) #elif _MSVC_TRADITIONAL #define EGGS_INVOKE(F, ...) (static_cast<decltype(::eggs::detail::invoke(F, __VA_ARGS__))>(F)(__VA_ARGS__)) #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F, __VA_ARGS__))>(F)( \ __VA_ARGS__)) #else #define EGGS_INVOKE(F, ...) (static_cast<decltype(::eggs::detail::invoke(F, ##__VA_ARGS__))>(F)(__VA_ARGS__)) #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F, ##__VA_ARGS__))>(F)( \ __VA_ARGS__)) #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -157,21 +168,20 @@ private: public: template <typename F, typename... Args> static constexpr auto call(F &&f, Args &&...args) noexcept(noexcept(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) -> decltype(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { static constexpr auto call(F &&f, Args &&...args) noexcept( noexcept(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) -> decltype(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); } }; // `static_cast<void>(INVOKE(f, t1, t2, ..., tN))` if `R` is _cv_ `void`. template<typename R> struct invoke_r<R, void> { template <typename R> struct invoke_r<R, void> { template <typename F, typename... Args> static constexpr auto call(F &&f, Args &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { static constexpr auto call(F &&f, Args &&...args) noexcept( noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { return static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)); } }; Loading @@ -187,11 +197,12 @@ struct invoke_r<R, void> { namespace eggs { /////////////////////////////////////////////////////////////////////////// namespace detail { template<typename T, typename Enable = void> struct invoke_result_impl {}; template <typename T, typename Enable = void> struct invoke_result_impl {}; template <typename F, typename... Ts> struct invoke_result_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> { struct invoke_result_impl<F(Ts...), decltype((void)EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> { using type = decltype(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...)); }; } // namespace detail Loading Loading @@ -223,7 +234,9 @@ template<typename T, typename Enable = void> struct is_invocable_impl : std::false_type {}; template <typename F, typename... Ts> struct is_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> struct is_invocable_impl<F(Ts...), decltype((void)EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> : std::true_type {}; } // namespace detail Loading @@ -237,7 +250,8 @@ struct is_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>() //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename Fn, typename... ArgTypes> struct is_invocable : detail::is_invocable_impl<Fn && (ArgTypes && ...)>::type {}; struct is_invocable : detail::is_invocable_impl<Fn && (ArgTypes && ...)>::type { }; #if __cpp_variable_templates //! template <class Fn, class... ArgTypes> // (C++14) Loading @@ -256,7 +270,9 @@ template<typename T, typename R, typename Enable = void> struct is_invocable_r_impl : std::false_type {}; template <typename F, typename... Ts, typename R> struct is_invocable_r_impl<F(Ts...), R, decltype((void) EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> struct is_invocable_r_impl<F(Ts...), R, decltype((void)EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> : std::true_type {}; } // namespace detail Loading @@ -270,7 +286,8 @@ struct is_invocable_r_impl<F(Ts...), R, decltype((void) EGGS_INVOKE_R(R, std::de //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename R, typename Fn, typename... ArgTypes> struct is_invocable_r : detail::is_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; struct is_invocable_r : detail::is_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; #if __cpp_variable_templates //! template <class R, class Fn, class... ArgTypes> // (C++14) Loading @@ -289,8 +306,12 @@ template<typename T, typename Enable = void> struct is_nothrow_invocable_impl : std::false_type {}; template <typename F, typename... Ts> struct is_nothrow_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> {}; struct is_nothrow_invocable_impl<F(Ts...), decltype((void)EGGS_INVOKE( std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> {}; } // namespace detail //! template <class Fn, class... ArgTypes> struct is_nothrow_invocable; Loading @@ -303,7 +324,8 @@ struct is_nothrow_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::decl //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename Fn, typename... ArgTypes> struct is_nothrow_invocable : detail::is_nothrow_invocable_impl<Fn && (ArgTypes && ...)>::type {}; struct is_nothrow_invocable : detail::is_nothrow_invocable_impl<Fn && (ArgTypes && ...)>::type {}; #if __cpp_variable_templates //! template <class Fn, class... ArgTypes> // (C++14) Loading @@ -313,7 +335,8 @@ template<typename Fn, typename... ArgTypes> #if __cpp_inline_variables inline #endif constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -322,23 +345,27 @@ template<typename T, typename R, typename Enable = void> struct is_nothrow_invocable_r_impl : std::false_type {}; template <typename F, typename... Ts, typename R> struct is_nothrow_invocable_r_impl<F(Ts...), R, struct is_nothrow_invocable_r_impl< F(Ts...), R, decltype((void)EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> {}; : std::integral_constant<bool, noexcept(EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> {}; } // namespace detail //! template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; //! template <class R, class Fn, class... ArgTypes> struct //! is_nothrow_invocable_r; //! //! - _Condition_: `eggs::is_invocable_r_v<R, Fn, ArgTypes...>` is `true` //! and the expression `INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)` //! is known not to throw any exceptions. //! and the expression `INVOKE(std::declval<Fn>(), //! std::declval<ArgTypes>()...)` is known not to throw any exceptions. //! //! - _Comments_: `Fn`, `R`, and all types in the template parameter pack //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename R, typename Fn, typename... ArgTypes> struct is_nothrow_invocable_r : detail::is_nothrow_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; struct is_nothrow_invocable_r : detail::is_nothrow_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; #if __cpp_variable_templates //! template <class R, class Fn, class... ArgTypes> // (C++14) Loading @@ -348,7 +375,8 @@ template<typename R, typename Fn, typename... ArgTypes> #if __cpp_inline_variables inline #endif constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -361,10 +389,9 @@ inline //! - _Remarks_: This function shall not participate in overload resolution //! unless `eggs::is_invocable_v<F, Args...>` is `true`. template <typename Fn, typename... ArgTypes> constexpr auto invoke(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)) { constexpr auto invoke(Fn &&f, ArgTypes &&...args) noexcept( noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)) { return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); } Loading @@ -378,14 +405,16 @@ invoke(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EG //! - _Remarks_: This function shall not participate in overload resolution //! unless `eggs::is_invocable_r_v<R, F, Args...>` is `true`. template <typename R, typename Fn, typename... ArgTypes> constexpr auto invoke_r(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...)) { constexpr auto invoke_r(Fn &&f, ArgTypes &&...args) noexcept( noexcept(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...)) { return EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...); } #undef EGGS_FWD } // namespace eggs namespace tile { using namespace eggs; } #endif /*EGGS_INVOKE_HPP*/ Loading
src/sled/exec/detail/invoke_result.h +182 −153 Original line number Diff line number Diff line Loading @@ -18,13 +18,15 @@ namespace detail { #define EGGS_FWD(...) static_cast<decltype(__VA_ARGS__) &&>(__VA_ARGS__) /////////////////////////////////////////////////////////////////////////// template<typename C, typename T, bool Ref, bool RefWrapper, bool IsFunction = std::is_function<T>::value> template <typename C, typename T, bool Ref, bool RefWrapper, bool IsFunction = std::is_function<T>::value> struct invoke_mem_ptr; // when `pm` is a pointer to member of a class `C` and // `is_base_of_v<C, remove_reference_t<T>>` is `true`; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -32,14 +34,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/f #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept(EGGS_FWD(t1).*pm)) -> decltype(EGGS_FWD(t1).*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept(EGGS_FWD(t1).*pm)) -> decltype(EGGS_FWD(t1).*pm) { return EGGS_FWD(t1).*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -47,9 +50,9 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/t #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...))) -> decltype((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...))) -> decltype((EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...)) { return (EGGS_FWD(t1).*pm)(EGGS_FWD(tn)...); } }; Loading @@ -57,7 +60,8 @@ struct invoke_mem_ptr<C, T, /*Ref=*/true, /*RefWrapper=*/false, /*IsFunction=*/t // when `pm` is a pointer to member of a class `C` and // `remove_cvref_t<T>` is a specialization of `reference_wrapper`; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -65,14 +69,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/f #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept(t1.get().*pm)) -> decltype(t1.get().*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept(t1.get().*pm)) -> decltype(t1.get().*pm) { return t1.get().*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -80,9 +85,9 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/t #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((t1.get().*pm)(EGGS_FWD(tn)...))) -> decltype((t1.get().*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept((t1.get().*pm)(EGGS_FWD(tn)...))) -> decltype((t1.get().*pm)(EGGS_FWD(tn)...)) { return (t1.get().*pm)(EGGS_FWD(tn)...); } }; Loading @@ -90,7 +95,8 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true, /*IsFunction=*/t // when `pm` is a pointer to member of a class `C` and `T` does not // satisfy the previous two items; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/false> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/false> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -98,14 +104,15 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/ #endif template <typename T1> constexpr auto operator()(T1 &&t1) const noexcept(noexcept((*EGGS_FWD(t1)).*pm)) -> decltype((*EGGS_FWD(t1)).*pm) { constexpr auto operator()(T1 &&t1) const noexcept(noexcept((*EGGS_FWD(t1)).*pm)) -> decltype((*EGGS_FWD(t1)).*pm) { return (*EGGS_FWD(t1)).*pm; } }; template <typename C, typename T> struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/true> { struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/true> { T C::*pm; #if !__cpp_aggregate_paren_init Loading @@ -113,26 +120,25 @@ struct invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/false, /*IsFunction=*/ #endif template <typename T1, typename... Tn> constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...))) -> decltype(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...)) { constexpr auto operator()(T1 &&t1, Tn &&...tn) const noexcept(noexcept(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...))) -> decltype(((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...)) { return ((*EGGS_FWD(t1)).*pm)(EGGS_FWD(tn)...); } }; /////////////////////////////////////////////////////////////////////////// template<typename F> auto invoke(F &&, ...) -> F &&; template <typename F> auto invoke(F &&, ...) -> F &&; template <typename T, typename C, typename T1> auto invoke(T C::*, T1 const &, ...) -> invoke_mem_ptr<C, T, auto invoke(T C::*, T1 const &, ...) -> invoke_mem_ptr<C, T, /*Ref=*/std::is_base_of<C, T1>::value, /*RefWrapper=*/false>; template <typename T, typename C, typename X> auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, T, auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, T, /*Ref=*/false, /*RefWrapper=*/true>; Loading @@ -141,11 +147,16 @@ auto invoke(T C::*, std::reference_wrapper<X>, ...) -> invoke_mem_ptr<C, //! - _Returns_: `INVOKE(F __VA_OPT__(,) __VA_ARGS__)`. #if __cplusplus > 201703L // C++20: P0306 #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F __VA_OPT__(, ) __VA_ARGS__))>(F)(__VA_ARGS__)) (static_cast<decltype(::eggs::detail::invoke( \ F __VA_OPT__(, ) __VA_ARGS__))>(F)(__VA_ARGS__)) #elif _MSVC_TRADITIONAL #define EGGS_INVOKE(F, ...) (static_cast<decltype(::eggs::detail::invoke(F, __VA_ARGS__))>(F)(__VA_ARGS__)) #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F, __VA_ARGS__))>(F)( \ __VA_ARGS__)) #else #define EGGS_INVOKE(F, ...) (static_cast<decltype(::eggs::detail::invoke(F, ##__VA_ARGS__))>(F)(__VA_ARGS__)) #define EGGS_INVOKE(F, ...) \ (static_cast<decltype(::eggs::detail::invoke(F, ##__VA_ARGS__))>(F)( \ __VA_ARGS__)) #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -157,21 +168,20 @@ private: public: template <typename F, typename... Args> static constexpr auto call(F &&f, Args &&...args) noexcept(noexcept(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) -> decltype(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { static constexpr auto call(F &&f, Args &&...args) noexcept( noexcept(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) -> decltype(conversion(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); } }; // `static_cast<void>(INVOKE(f, t1, t2, ..., tN))` if `R` is _cv_ `void`. template<typename R> struct invoke_r<R, void> { template <typename R> struct invoke_r<R, void> { template <typename F, typename... Args> static constexpr auto call(F &&f, Args &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { static constexpr auto call(F &&f, Args &&...args) noexcept( noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) { return static_cast<void>(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)); } }; Loading @@ -187,11 +197,12 @@ struct invoke_r<R, void> { namespace eggs { /////////////////////////////////////////////////////////////////////////// namespace detail { template<typename T, typename Enable = void> struct invoke_result_impl {}; template <typename T, typename Enable = void> struct invoke_result_impl {}; template <typename F, typename... Ts> struct invoke_result_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> { struct invoke_result_impl<F(Ts...), decltype((void)EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> { using type = decltype(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...)); }; } // namespace detail Loading Loading @@ -223,7 +234,9 @@ template<typename T, typename Enable = void> struct is_invocable_impl : std::false_type {}; template <typename F, typename... Ts> struct is_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> struct is_invocable_impl<F(Ts...), decltype((void)EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> : std::true_type {}; } // namespace detail Loading @@ -237,7 +250,8 @@ struct is_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>() //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename Fn, typename... ArgTypes> struct is_invocable : detail::is_invocable_impl<Fn && (ArgTypes && ...)>::type {}; struct is_invocable : detail::is_invocable_impl<Fn && (ArgTypes && ...)>::type { }; #if __cpp_variable_templates //! template <class Fn, class... ArgTypes> // (C++14) Loading @@ -256,7 +270,9 @@ template<typename T, typename R, typename Enable = void> struct is_invocable_r_impl : std::false_type {}; template <typename F, typename... Ts, typename R> struct is_invocable_r_impl<F(Ts...), R, decltype((void) EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> struct is_invocable_r_impl<F(Ts...), R, decltype((void)EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> : std::true_type {}; } // namespace detail Loading @@ -270,7 +286,8 @@ struct is_invocable_r_impl<F(Ts...), R, decltype((void) EGGS_INVOKE_R(R, std::de //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename R, typename Fn, typename... ArgTypes> struct is_invocable_r : detail::is_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; struct is_invocable_r : detail::is_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; #if __cpp_variable_templates //! template <class R, class Fn, class... ArgTypes> // (C++14) Loading @@ -289,8 +306,12 @@ template<typename T, typename Enable = void> struct is_nothrow_invocable_impl : std::false_type {}; template <typename F, typename... Ts> struct is_nothrow_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> {}; struct is_nothrow_invocable_impl<F(Ts...), decltype((void)EGGS_INVOKE( std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE(std::declval<F>(), std::declval<Ts>()...))> {}; } // namespace detail //! template <class Fn, class... ArgTypes> struct is_nothrow_invocable; Loading @@ -303,7 +324,8 @@ struct is_nothrow_invocable_impl<F(Ts...), decltype((void) EGGS_INVOKE(std::decl //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename Fn, typename... ArgTypes> struct is_nothrow_invocable : detail::is_nothrow_invocable_impl<Fn && (ArgTypes && ...)>::type {}; struct is_nothrow_invocable : detail::is_nothrow_invocable_impl<Fn && (ArgTypes && ...)>::type {}; #if __cpp_variable_templates //! template <class Fn, class... ArgTypes> // (C++14) Loading @@ -313,7 +335,8 @@ template<typename Fn, typename... ArgTypes> #if __cpp_inline_variables inline #endif constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -322,23 +345,27 @@ template<typename T, typename R, typename Enable = void> struct is_nothrow_invocable_r_impl : std::false_type {}; template <typename F, typename... Ts, typename R> struct is_nothrow_invocable_r_impl<F(Ts...), R, struct is_nothrow_invocable_r_impl< F(Ts...), R, decltype((void)EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> : std::integral_constant<bool, noexcept(EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> {}; : std::integral_constant<bool, noexcept(EGGS_INVOKE_R(R, std::declval<F>(), std::declval<Ts>()...))> {}; } // namespace detail //! template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; //! template <class R, class Fn, class... ArgTypes> struct //! is_nothrow_invocable_r; //! //! - _Condition_: `eggs::is_invocable_r_v<R, Fn, ArgTypes...>` is `true` //! and the expression `INVOKE(std::declval<Fn>(), std::declval<ArgTypes>()...)` //! is known not to throw any exceptions. //! and the expression `INVOKE(std::declval<Fn>(), //! std::declval<ArgTypes>()...)` is known not to throw any exceptions. //! //! - _Comments_: `Fn`, `R`, and all types in the template parameter pack //! `ArgTypes` shall be complete types, _cv_ `void`, or arrays of //! unknown bound. template <typename R, typename Fn, typename... ArgTypes> struct is_nothrow_invocable_r : detail::is_nothrow_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; struct is_nothrow_invocable_r : detail::is_nothrow_invocable_r_impl<Fn && (ArgTypes && ...), R>::type {}; #if __cpp_variable_templates //! template <class R, class Fn, class... ArgTypes> // (C++14) Loading @@ -348,7 +375,8 @@ template<typename R, typename Fn, typename... ArgTypes> #if __cpp_inline_variables inline #endif constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; #endif /////////////////////////////////////////////////////////////////////////// Loading @@ -361,10 +389,9 @@ inline //! - _Remarks_: This function shall not participate in overload resolution //! unless `eggs::is_invocable_v<F, Args...>` is `true`. template <typename Fn, typename... ArgTypes> constexpr auto invoke(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)) { constexpr auto invoke(Fn &&f, ArgTypes &&...args) noexcept( noexcept(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)) { return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); } Loading @@ -378,14 +405,16 @@ invoke(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE(EGGS_FWD(f), EG //! - _Remarks_: This function shall not participate in overload resolution //! unless `eggs::is_invocable_r_v<R, F, Args...>` is `true`. template <typename R, typename Fn, typename... ArgTypes> constexpr auto invoke_r(Fn &&f, ArgTypes &&...args) noexcept(noexcept(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...)) { constexpr auto invoke_r(Fn &&f, ArgTypes &&...args) noexcept( noexcept(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...))) -> decltype(EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...)) { return EGGS_INVOKE_R(R, EGGS_FWD(f), EGGS_FWD(args)...); } #undef EGGS_FWD } // namespace eggs namespace tile { using namespace eggs; } #endif /*EGGS_INVOKE_HPP*/