to C++17, remove custom invoke impl

This commit is contained in:
BlackMATov
2019-12-28 12:15:29 +07:00
parent dd92ea6fb1
commit 61a76715a8
6 changed files with 40 additions and 830 deletions

View File

@@ -1,4 +1,4 @@
# 3.8 version is required for `cxx_std_14` # 3.8 version is required for `cxx_std_17`
cmake_minimum_required(VERSION 3.8 FATAL_ERROR) cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
if(NOT DEFINED PROJECT_NAME) if(NOT DEFINED PROJECT_NAME)
@@ -9,7 +9,7 @@ project(promise.hpp)
add_library(${PROJECT_NAME} INTERFACE) add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE headers) target_include_directories(${PROJECT_NAME} INTERFACE headers)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_14) target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
if(BUILD_AS_STANDALONE) if(BUILD_AS_STANDALONE)
option(BUILD_WITH_UNTESTS "Build with unit tests" ON) option(BUILD_WITH_UNTESTS "Build with unit tests" ON)

View File

@@ -1,248 +0,0 @@
/*******************************************************************************
* This file is part of the "https://github.com/blackmatov/invoke.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include <tuple>
#include <utility>
#include <functional>
#include <type_traits>
#define INVOKE_HPP_NOEXCEPT_RETURN(...) \
noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; }
#define INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \
noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; }
//
// void_t
//
namespace invoke_hpp
{
namespace impl
{
template < typename... Args >
struct make_void {
using type = void;
};
}
template < typename... Args >
using void_t = typename impl::make_void<Args...>::type;
}
//
// is_reference_wrapper
//
namespace invoke_hpp
{
namespace impl
{
template < typename T >
struct is_reference_wrapper_impl
: std::false_type {};
template < typename U >
struct is_reference_wrapper_impl<std::reference_wrapper<U>>
: std::true_type {};
}
template < typename T >
struct is_reference_wrapper
: impl::is_reference_wrapper_impl<std::remove_cv_t<T>> {};
}
//
// invoke
//
namespace invoke_hpp
{
namespace impl
{
//
// invoke_member_object_impl
//
template
<
typename Base, typename F, typename Derived,
typename std::enable_if_t<std::is_base_of<Base, std::decay_t<Derived>>::value, int> = 0
>
constexpr auto invoke_member_object_impl(F Base::* f, Derived&& ref)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
std::forward<Derived>(ref).*f)
template
<
typename Base, typename F, typename RefWrap,
typename std::enable_if_t<is_reference_wrapper<std::decay_t<RefWrap>>::value, int> = 0
>
constexpr auto invoke_member_object_impl(F Base::* f, RefWrap&& ref)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
ref.get().*f)
template
<
typename Base, typename F, typename Pointer,
typename std::enable_if_t<
!std::is_base_of<Base, std::decay_t<Pointer>>::value &&
!is_reference_wrapper<std::decay_t<Pointer>>::value
, int> = 0
>
constexpr auto invoke_member_object_impl(F Base::* f, Pointer&& ptr)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
(*std::forward<Pointer>(ptr)).*f)
//
// invoke_member_function_impl
//
template
<
typename Base, typename F, typename Derived, typename... Args,
typename std::enable_if_t<std::is_base_of<Base, std::decay_t<Derived>>::value, int> = 0
>
constexpr auto invoke_member_function_impl(F Base::* f, Derived&& ref, Args&&... args)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
(std::forward<Derived>(ref).*f)(std::forward<Args>(args)...))
template
<
typename Base, typename F, typename RefWrap, typename... Args,
typename std::enable_if_t<is_reference_wrapper<std::decay_t<RefWrap>>::value, int> = 0
>
constexpr auto invoke_member_function_impl(F Base::* f, RefWrap&& ref, Args&&... args)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
(ref.get().*f)(std::forward<Args>(args)...))
template
<
typename Base, typename F, typename Pointer, typename... Args,
typename std::enable_if_t<
!std::is_base_of<Base, std::decay_t<Pointer>>::value &&
!is_reference_wrapper<std::decay_t<Pointer>>::value
, int> = 0
>
constexpr auto invoke_member_function_impl(F Base::* f, Pointer&& ptr, Args&&... args)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
((*std::forward<Pointer>(ptr)).*f)(std::forward<Args>(args)...))
}
template
<
typename F, typename... Args,
typename std::enable_if_t<!std::is_member_pointer<std::decay_t<F>>::value, int> = 0
>
constexpr auto invoke(F&& f, Args&&... args)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
std::forward<F>(f)(std::forward<Args>(args)...))
template
<
typename F, typename T,
typename std::enable_if_t<std::is_member_object_pointer<std::decay_t<F>>::value, int> = 0
>
constexpr auto invoke(F&& f, T&& t)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
impl::invoke_member_object_impl(std::forward<F>(f), std::forward<T>(t)))
template
<
typename F, typename... Args,
typename std::enable_if_t<std::is_member_function_pointer<std::decay_t<F>>::value, int> = 0
>
constexpr auto invoke(F&& f, Args&&... args)
INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(
impl::invoke_member_function_impl(std::forward<F>(f), std::forward<Args>(args)...))
}
//
// invoke_result
//
namespace invoke_hpp
{
namespace impl
{
struct invoke_result_impl_tag {};
template < typename Void, typename F, typename... Args >
struct invoke_result_impl {};
template < typename F, typename... Args >
struct invoke_result_impl<void_t<invoke_result_impl_tag, decltype(invoke_hpp::invoke(std::declval<F>(), std::declval<Args>()...))>, F, Args...> {
using type = decltype(invoke_hpp::invoke(std::declval<F>(), std::declval<Args>()...));
};
}
template < typename F, typename... Args >
struct invoke_result
: impl::invoke_result_impl<void, F, Args...> {};
template < typename F, typename... Args >
using invoke_result_t = typename invoke_result<F, Args...>::type;
}
//
// is_invocable
//
namespace invoke_hpp
{
namespace impl
{
struct is_invocable_r_impl_tag {};
template < typename Void, typename R, typename F, typename... Args >
struct is_invocable_r_impl
: std::false_type {};
template < typename R, typename F, typename... Args >
struct is_invocable_r_impl<void_t<is_invocable_r_impl_tag, invoke_result_t<F, Args...>>, R, F, Args...>
: std::conditional_t<
std::is_void<R>::value,
std::true_type,
std::is_convertible<invoke_result_t<F, Args...>, R>> {};
}
template < typename R, typename F, typename... Args >
struct is_invocable_r
: impl::is_invocable_r_impl<void, R, F, Args...> {};
template < typename F, typename... Args >
using is_invocable = is_invocable_r<void, F, Args...>;
}
//
// apply
//
namespace invoke_hpp
{
namespace impl
{
template < typename F, typename Tuple, std::size_t... I >
constexpr decltype(auto) apply_impl(F&& f, Tuple&& args, std::index_sequence<I...>)
INVOKE_HPP_NOEXCEPT_RETURN(
invoke_hpp::invoke(
std::forward<F>(f),
std::get<I>(std::forward<Tuple>(args))...))
}
template < typename F, typename Tuple >
constexpr decltype(auto) apply(F&& f, Tuple&& args)
INVOKE_HPP_NOEXCEPT_RETURN(
impl::apply_impl(
std::forward<F>(f),
std::forward<Tuple>(args),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>()))
}
#undef INVOKE_HPP_NOEXCEPT_RETURN
#undef INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN

View File

@@ -6,22 +6,6 @@
#pragma once #pragma once
#include <cstdint>
#include <cassert>
#include <tuple>
#include <mutex>
#include <atomic>
#include <thread>
#include <chrono>
#include <memory>
#include <vector>
#include <utility>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include <condition_variable>
#include "promise.hpp" #include "promise.hpp"
namespace jobber_hpp namespace jobber_hpp
@@ -58,7 +42,7 @@ namespace jobber_hpp
std::size_t>; std::size_t>;
template < typename F, typename... Args > template < typename F, typename... Args >
using async_invoke_result_t = invoke_hpp::invoke_result_t< using async_invoke_result_t = std::invoke_result_t<
std::decay_t<F>, std::decay_t<F>,
std::decay_t<Args>...>; std::decay_t<Args>...>;
@@ -378,7 +362,7 @@ namespace jobber_hpp
template < typename R, typename F, typename... Args > template < typename R, typename F, typename... Args >
void jobber::concrete_task<R, F, Args...>::run() noexcept { void jobber::concrete_task<R, F, Args...>::run() noexcept {
try { try {
R value = invoke_hpp::apply(std::move(f_), std::move(args_)); R value = std::apply(std::move(f_), std::move(args_));
promise_.resolve(std::move(value)); promise_.resolve(std::move(value));
} catch (...) { } catch (...) {
promise_.reject(std::current_exception()); promise_.reject(std::current_exception());
@@ -408,7 +392,7 @@ namespace jobber_hpp
template < typename F, typename... Args > template < typename F, typename... Args >
void jobber::concrete_task<void, F, Args...>::run() noexcept { void jobber::concrete_task<void, F, Args...>::run() noexcept {
try { try {
invoke_hpp::apply(std::move(f_), std::move(args_)); std::apply(std::move(f_), std::move(args_));
promise_.resolve(); promise_.resolve();
} catch (...) { } catch (...) {
promise_.reject(std::current_exception()); promise_.reject(std::current_exception());

View File

@@ -13,6 +13,7 @@
#include <tuple> #include <tuple>
#include <mutex> #include <mutex>
#include <atomic> #include <atomic>
#include <thread>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -24,8 +25,6 @@
#include <type_traits> #include <type_traits>
#include <condition_variable> #include <condition_variable>
#include "invoke.hpp"
namespace promise_hpp namespace promise_hpp
{ {
// //
@@ -180,7 +179,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF,T> > , typename ResolveFR = std::invoke_result_t<ResolveF,T> >
std::enable_if_t< std::enable_if_t<
is_promise<ResolveFR>::value && std::is_void<typename ResolveFR::value_type>::value, is_promise<ResolveFR>::value && std::is_void<typename ResolveFR::value_type>::value,
promise<typename ResolveFR::value_type>> promise<typename ResolveFR::value_type>>
@@ -191,7 +190,7 @@ namespace promise_hpp
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
auto np = invoke_hpp::invoke( auto np = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
std::move(np).then([n]() mutable { std::move(np).then([n]() mutable {
@@ -207,7 +206,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF,T> > , typename ResolveFR = std::invoke_result_t<ResolveF,T> >
std::enable_if_t< std::enable_if_t<
is_promise<ResolveFR>::value && !std::is_void<typename ResolveFR::value_type>::value, is_promise<ResolveFR>::value && !std::is_void<typename ResolveFR::value_type>::value,
promise<typename ResolveFR::value_type>> promise<typename ResolveFR::value_type>>
@@ -218,7 +217,7 @@ namespace promise_hpp
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
auto np = invoke_hpp::invoke( auto np = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
std::move(np).then([n](auto&& nv) mutable { std::move(np).then([n](auto&& nv) mutable {
@@ -238,7 +237,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
return make_all_promise(std::move(r)); return make_all_promise(std::move(r));
@@ -250,7 +249,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
return make_race_promise(std::move(r)); return make_race_promise(std::move(r));
@@ -262,7 +261,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
return make_tuple_promise(std::move(r)); return make_tuple_promise(std::move(r));
@@ -271,7 +270,7 @@ namespace promise_hpp
template < typename ResolveF template < typename ResolveF
, typename RejectF , typename RejectF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF,T> > , typename ResolveFR = std::invoke_result_t<ResolveF,T> >
std::enable_if_t< std::enable_if_t<
!is_promise<ResolveFR>::value, !is_promise<ResolveFR>::value,
promise<ResolveFR>> promise<ResolveFR>>
@@ -286,7 +285,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF,T> > , typename ResolveFR = std::invoke_result_t<ResolveF,T> >
std::enable_if_t< std::enable_if_t<
!is_promise<ResolveFR>::value, !is_promise<ResolveFR>::value,
promise<ResolveFR>> promise<ResolveFR>>
@@ -443,7 +442,7 @@ namespace promise_hpp
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
if ( has_reject ) { if ( has_reject ) {
try { try {
invoke_hpp::invoke( std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
e); e);
n.resolve(); n.resolve();
@@ -460,7 +459,7 @@ namespace promise_hpp
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
try { try {
invoke_hpp::invoke( std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
n.resolve(); n.resolve();
@@ -488,7 +487,7 @@ namespace promise_hpp
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
if ( has_reject ) { if ( has_reject ) {
try { try {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
e); e);
n.resolve(std::move(r)); n.resolve(std::move(r));
@@ -505,7 +504,7 @@ namespace promise_hpp
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](auto&& v) mutable { ](auto&& v) mutable {
try { try {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
std::forward<decltype(v)>(v)); std::forward<decltype(v)>(v));
n.resolve(std::move(r)); n.resolve(std::move(r));
@@ -521,11 +520,11 @@ namespace promise_hpp
template < typename ResolveF, typename RejectF > template < typename ResolveF, typename RejectF >
void add_handlers_(ResolveF&& resolve, RejectF&& reject) { void add_handlers_(ResolveF&& resolve, RejectF&& reject) {
if ( status_ == status::resolved ) { if ( status_ == status::resolved ) {
invoke_hpp::invoke( std::invoke(
std::forward<ResolveF>(resolve), std::forward<ResolveF>(resolve),
storage_.value()); storage_.value());
} else if ( status_ == status::rejected ) { } else if ( status_ == status::rejected ) {
invoke_hpp::invoke( std::invoke(
std::forward<RejectF>(reject), std::forward<RejectF>(reject),
exception_); exception_);
} else { } else {
@@ -616,7 +615,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF> > , typename ResolveFR = std::invoke_result_t<ResolveF> >
std::enable_if_t< std::enable_if_t<
is_promise<ResolveFR>::value && std::is_void<typename ResolveFR::value_type>::value, is_promise<ResolveFR>::value && std::is_void<typename ResolveFR::value_type>::value,
promise<typename ResolveFR::value_type>> promise<typename ResolveFR::value_type>>
@@ -627,7 +626,7 @@ namespace promise_hpp
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
auto np = invoke_hpp::invoke( auto np = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
std::move(np).then([n]() mutable { std::move(np).then([n]() mutable {
n.resolve(); n.resolve();
@@ -642,7 +641,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF> > , typename ResolveFR = std::invoke_result_t<ResolveF> >
std::enable_if_t< std::enable_if_t<
is_promise<ResolveFR>::value && !std::is_void<typename ResolveFR::value_type>::value, is_promise<ResolveFR>::value && !std::is_void<typename ResolveFR::value_type>::value,
promise<typename ResolveFR::value_type>> promise<typename ResolveFR::value_type>>
@@ -653,7 +652,7 @@ namespace promise_hpp
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
auto np = invoke_hpp::invoke( auto np = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
std::move(np).then([n](auto&& nv) mutable { std::move(np).then([n](auto&& nv) mutable {
n.resolve(std::forward<decltype(nv)>(nv)); n.resolve(std::forward<decltype(nv)>(nv));
@@ -672,7 +671,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
return make_all_promise(std::move(r)); return make_all_promise(std::move(r));
}); });
@@ -683,7 +682,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
return make_race_promise(std::move(r)); return make_race_promise(std::move(r));
}); });
@@ -694,7 +693,7 @@ namespace promise_hpp
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
return make_tuple_promise(std::move(r)); return make_tuple_promise(std::move(r));
}); });
@@ -702,7 +701,7 @@ namespace promise_hpp
template < typename ResolveF template < typename ResolveF
, typename RejectF , typename RejectF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF> > , typename ResolveFR = std::invoke_result_t<ResolveF> >
std::enable_if_t< std::enable_if_t<
!is_promise<ResolveFR>::value, !is_promise<ResolveFR>::value,
promise<ResolveFR>> promise<ResolveFR>>
@@ -717,7 +716,7 @@ namespace promise_hpp
} }
template < typename ResolveF template < typename ResolveF
, typename ResolveFR = invoke_hpp::invoke_result_t<ResolveF> > , typename ResolveFR = std::invoke_result_t<ResolveF> >
std::enable_if_t< std::enable_if_t<
!is_promise<ResolveFR>::value, !is_promise<ResolveFR>::value,
promise<ResolveFR>> promise<ResolveFR>>
@@ -869,7 +868,7 @@ namespace promise_hpp
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
if ( has_reject ) { if ( has_reject ) {
try { try {
invoke_hpp::invoke( std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
e); e);
n.resolve(); n.resolve();
@@ -886,7 +885,7 @@ namespace promise_hpp
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
try { try {
invoke_hpp::invoke( std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
n.resolve(); n.resolve();
} catch (...) { } catch (...) {
@@ -913,7 +912,7 @@ namespace promise_hpp
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
if ( has_reject ) { if ( has_reject ) {
try { try {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
e); e);
n.resolve(std::move(r)); n.resolve(std::move(r));
@@ -930,7 +929,7 @@ namespace promise_hpp
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
]() mutable { ]() mutable {
try { try {
auto r = invoke_hpp::invoke( auto r = std::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
n.resolve(std::move(r)); n.resolve(std::move(r));
} catch (...) { } catch (...) {
@@ -945,10 +944,10 @@ namespace promise_hpp
template < typename ResolveF, typename RejectF > template < typename ResolveF, typename RejectF >
void add_handlers_(ResolveF&& resolve, RejectF&& reject) { void add_handlers_(ResolveF&& resolve, RejectF&& reject) {
if ( status_ == status::resolved ) { if ( status_ == status::resolved ) {
invoke_hpp::invoke( std::invoke(
std::forward<ResolveF>(resolve)); std::forward<ResolveF>(resolve));
} else if ( status_ == status::rejected ) { } else if ( status_ == status::rejected ) {
invoke_hpp::invoke( std::invoke(
std::forward<RejectF>(reject), std::forward<RejectF>(reject),
exception_); exception_);
} else { } else {
@@ -1032,7 +1031,7 @@ namespace promise_hpp
}; };
try { try {
invoke_hpp::invoke( std::invoke(
std::forward<F>(f), std::forward<F>(f),
std::move(resolver), std::move(resolver),
std::move(rejector)); std::move(rejector));

View File

@@ -6,21 +6,6 @@
#pragma once #pragma once
#include <cstdint>
#include <cassert>
#include <tuple>
#include <mutex>
#include <atomic>
#include <chrono>
#include <memory>
#include <vector>
#include <utility>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include <condition_variable>
#include "promise.hpp" #include "promise.hpp"
namespace scheduler_hpp namespace scheduler_hpp
@@ -57,7 +42,7 @@ namespace scheduler_hpp
std::size_t>; std::size_t>;
template < typename F, typename... Args > template < typename F, typename... Args >
using schedule_invoke_result_t = invoke_hpp::invoke_result_t< using schedule_invoke_result_t = std::invoke_result_t<
std::decay_t<F>, std::decay_t<F>,
std::decay_t<Args>...>; std::decay_t<Args>...>;
@@ -286,7 +271,7 @@ namespace scheduler_hpp
template < typename R, typename F, typename... Args > template < typename R, typename F, typename... Args >
void scheduler::concrete_task<R, F, Args...>::run() noexcept { void scheduler::concrete_task<R, F, Args...>::run() noexcept {
try { try {
R value = invoke_hpp::apply(std::move(f_), std::move(args_)); R value = std::apply(std::move(f_), std::move(args_));
promise_.resolve(std::move(value)); promise_.resolve(std::move(value));
} catch (...) { } catch (...) {
promise_.reject(std::current_exception()); promise_.reject(std::current_exception());
@@ -316,7 +301,7 @@ namespace scheduler_hpp
template < typename F, typename... Args > template < typename F, typename... Args >
void scheduler::concrete_task<void, F, Args...>::run() noexcept { void scheduler::concrete_task<void, F, Args...>::run() noexcept {
try { try {
invoke_hpp::apply(std::move(f_), std::move(args_)); std::apply(std::move(f_), std::move(args_));
promise_.resolve(); promise_.resolve();
} catch (...) { } catch (...) {
promise_.reject(std::current_exception()); promise_.reject(std::current_exception());

View File

@@ -1,510 +0,0 @@
/*******************************************************************************
* This file is part of the "https://github.com/blackmatov/invoke.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#define CATCH_CONFIG_FAST_COMPILE
#include <catch2/catch.hpp>
#include <promise.hpp/invoke.hpp>
namespace inv = invoke_hpp;
namespace
{
void simple_static_function() {
}
int simple_static_function_r() {
return 42;
}
int simple_static_function_r_with_arg(int v) {
return v;
}
const int& simple_static_function_r_with_ref_arg(const int& v) {
return v;
}
class obj_t {
public:
int value = 42;
const int value_c = 42;
void member() {
}
int member_r() {
return 42;
}
int member_r_with_arg(int v) {
return v;
}
const int& member_r_with_ref_arg(const int& v) {
return v;
}
};
class obj2_t {
};
}
TEST_CASE("invoke"){
SECTION("invoke_functions"){
inv::invoke(simple_static_function);
REQUIRE(inv::invoke(simple_static_function_r) == 42);
REQUIRE(inv::invoke(simple_static_function_r_with_arg, 42) == 42);
{
int v = 42;
REQUIRE(&inv::invoke(simple_static_function_r_with_ref_arg, v) == &v);
}
}
SECTION("invoke_members"){
obj_t o;
inv::invoke(&obj_t::member, o);
inv::invoke(&obj_t::member, &o);
inv::invoke(&obj_t::member, std::ref(o));
REQUIRE(inv::invoke(&obj_t::member_r, o) == 42);
REQUIRE(inv::invoke(&obj_t::member_r, &o) == 42);
REQUIRE(inv::invoke(&obj_t::member_r, std::ref(o)) == 42);
REQUIRE(inv::invoke(&obj_t::member_r_with_arg, o, 42) == 42);
REQUIRE(inv::invoke(&obj_t::member_r_with_arg, &o, 42) == 42);
REQUIRE(inv::invoke(&obj_t::member_r_with_arg, std::ref(o), 42) == 42);
{
int v = 42;
REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, o, std::ref(v)) == &v);
REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, &o, std::ref(v)) == &v);
REQUIRE(&inv::invoke(&obj_t::member_r_with_ref_arg, std::ref(o), std::ref(v)) == &v);
}
}
SECTION("invoke_member_objects"){
obj_t o;
REQUIRE(inv::invoke(&obj_t::value, o) == 42);
REQUIRE(inv::invoke(&obj_t::value, &o) == 42);
REQUIRE(inv::invoke(&obj_t::value, std::ref(o)) == 42);
REQUIRE(inv::invoke(&obj_t::value_c, o) == 42);
REQUIRE(inv::invoke(&obj_t::value_c, &o) == 42);
REQUIRE(inv::invoke(&obj_t::value_c, std::ref(o)) == 42);
}
}
TEST_CASE("invoke_result"){
SECTION("invoke_result_functions"){
static_assert(
std::is_same<
void,
inv::invoke_result_t<decltype(simple_static_function)>>::value,
"unit test fail");
static_assert(
std::is_same<
int,
inv::invoke_result_t<decltype(simple_static_function_r)>>::value,
"unit test fail");
static_assert(
std::is_same<
int,
inv::invoke_result_t<decltype(simple_static_function_r_with_arg), int>>::value,
"unit test fail");
static_assert(
std::is_same<
const int&,
inv::invoke_result_t<decltype(simple_static_function_r_with_ref_arg), const int&>>::value,
"unit test fail");
}
SECTION("invoke_result_members"){
static_assert(
std::is_same<void,
inv::invoke_result_t<decltype(&obj_t::member), obj_t>>::value,
"unit test fail");
static_assert(
std::is_same<void,
inv::invoke_result_t<decltype(&obj_t::member), obj_t*>>::value,
"unit test fail");
static_assert(
std::is_same<void,
inv::invoke_result_t<decltype(&obj_t::member), std::reference_wrapper<obj_t>>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r), obj_t>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r), obj_t*>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r_with_arg), obj_t, int>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r_with_arg), obj_t*, int>>::value,
"unit test fail");
static_assert(
std::is_same<int,
inv::invoke_result_t<decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>>::value,
"unit test fail");
static_assert(
std::is_same<const int&,
inv::invoke_result_t<decltype(&obj_t::member_r_with_ref_arg), obj_t, const int&>>::value,
"unit test fail");
static_assert(
std::is_same<const int&,
inv::invoke_result_t<decltype(&obj_t::member_r_with_ref_arg), obj_t*, const int&>>::value,
"unit test fail");
static_assert(
std::is_same<const int&,
inv::invoke_result_t<decltype(&obj_t::member_r_with_ref_arg), std::reference_wrapper<obj_t>, const int&>>::value,
"unit test fail");
}
}
TEST_CASE("is_invocable"){
SECTION("is_invocable_functions"){
static_assert(
inv::is_invocable<decltype(simple_static_function)>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(simple_static_function_r_with_arg), int>::value,
"unit test fail");
}
SECTION("is_not_invocable_functions"){
static_assert(
!inv::is_invocable<decltype(simple_static_function), int>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(simple_static_function_r), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(simple_static_function_r_with_arg)>::value,
"unit test fail");
}
SECTION("is_invocable_members"){
static_assert(
inv::is_invocable<decltype(&obj_t::member), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r_with_arg), obj_t, int>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r_with_arg), obj_t*, int>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>::value,
"unit test fail");
}
SECTION("is_not_invocable_members"){
static_assert(
!inv::is_invocable<decltype(&obj_t::member)>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member), int>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member), std::reference_wrapper<obj_t>*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r), obj_t**>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r), obj2_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r), std::reference_wrapper<obj2_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r_with_arg), obj_t, char*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r_with_arg), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj2_t>, int>::value,
"unit test fail");
}
SECTION("is_invocable_objects"){
static_assert(
inv::is_invocable<decltype(&obj_t::value), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::value), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::value), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::value_c), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::value_c), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable<decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
}
SECTION("is_not_invocable_objects"){
static_assert(
!inv::is_invocable<decltype(&obj_t::value)>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::value), obj2_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::value), obj_t, int>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::value_c), obj_t**>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::value_c), obj_t*, obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable<decltype(&obj_t::value_c), std::reference_wrapper<obj_t**>>::value,
"unit test fail");
}
}
TEST_CASE("is_invocable_r"){
SECTION("is_invocable_r_functions"){
static_assert(
inv::is_invocable_r<void, decltype(simple_static_function)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<const int&, decltype(simple_static_function_r_with_arg), const int&>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_functions"){
static_assert(
!inv::is_invocable_r<void, decltype(simple_static_function), int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(simple_static_function_r), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<const int&, decltype(simple_static_function_r_with_arg), const obj2_t&>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(simple_static_function)>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(simple_static_function_r_with_arg), const int&>::value,
"unit test fail");
}
SECTION("is_invocable_r_members"){
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), obj_t, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), obj_t*, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_members"){
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member_r), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member_r), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member_r), std::reference_wrapper<obj2_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member_r_with_arg), obj_t, int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member_r_with_arg), obj_t*, int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
}
SECTION("is_invocable_r_objects"){
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::value), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_objects"){
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::value), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::value), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::value), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<void, decltype(&obj_t::value), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::value_c), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::value_c), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj2_t, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<void, decltype(&obj_t::value_c), std::reference_wrapper<obj_t**>>::value,
"unit test fail");
}
}
TEST_CASE("apply"){
SECTION("apply_functions"){
inv::apply(simple_static_function, std::make_tuple());
REQUIRE(inv::apply(simple_static_function_r, std::make_tuple()) == 42);
REQUIRE(inv::apply(simple_static_function_r_with_arg, std::make_tuple(42)) == 42);
{
int v = 42;
REQUIRE(&inv::apply(simple_static_function_r_with_ref_arg, std::make_tuple(std::ref(v))) == &v);
}
}
SECTION("apply_members"){
obj_t o;
inv::apply(&obj_t::member, std::make_tuple(o));
inv::apply(&obj_t::member, std::make_tuple(&o));
inv::apply(&obj_t::member, std::make_tuple(std::ref(o)));
REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(o)) == 42);
REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(&o)) == 42);
REQUIRE(inv::apply(&obj_t::member_r, std::make_tuple(std::ref(o))) == 42);
REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(o, 42)) == 42);
REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(&o, 42)) == 42);
REQUIRE(inv::apply(&obj_t::member_r_with_arg, std::make_tuple(std::ref(o), 42)) == 42);
{
int v = 42;
REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(o, std::ref(v))) == &v);
REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(&o, std::ref(v))) == &v);
REQUIRE(&inv::apply(&obj_t::member_r_with_ref_arg, std::make_tuple(std::ref(o), std::ref(v))) == &v);
}
}
SECTION("apply_member_objects"){
obj_t o;
REQUIRE(inv::apply(&obj_t::value, std::make_tuple(o)) == 42);
REQUIRE(inv::apply(&obj_t::value, std::make_tuple(&o)) == 42);
REQUIRE(inv::apply(&obj_t::value, std::make_tuple(std::ref(o))) == 42);
REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(o)) == 42);
REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(&o)) == 42);
REQUIRE(inv::apply(&obj_t::value_c, std::make_tuple(std::ref(o))) == 42);
}
}