mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Use new types instead of aliases for type erasures
* Makes compiler output much more readable This is configurateable through CONTINUABLE_WITH_IMMEDIATE_TYPES, and automatically enabled for debug builds but disabled for release builds. * Remove the old continuable-trait.hpp header * Make the signature of continuable not dependent anymore on any size of the arguments which fixes the compilation with forward declared types. Thanks Rogiel for the correspoding bug report. Closes #11
This commit is contained in:
parent
2d5aa36b67
commit
c066940d8d
@ -20,6 +20,7 @@ matrix:
|
||||
- ninja-build
|
||||
env:
|
||||
- COMPILER=g++-6
|
||||
- BUILD_CONFIG=Debug
|
||||
- WITH_NO_EXCEPTIONS=OFF
|
||||
- WITH_AWAIT=OFF
|
||||
- WITH_LIGHT_TESTS=ON
|
||||
@ -36,6 +37,7 @@ matrix:
|
||||
- ninja-build
|
||||
env:
|
||||
- COMPILER=clang++-5.0
|
||||
- BUILD_CONFIG=Release
|
||||
- WITH_NO_EXCEPTIONS=OFF
|
||||
- WITH_AWAIT=OFF
|
||||
- WITH_LIGHT_TESTS=OFF
|
||||
@ -52,6 +54,7 @@ matrix:
|
||||
- ninja-build
|
||||
env:
|
||||
- COMPILER=clang++-5.0
|
||||
- BUILD_CONFIG=Debug
|
||||
- WITH_NO_EXCEPTIONS=ON
|
||||
- WITH_AWAIT=ON
|
||||
- WITH_LIGHT_TESTS=ON
|
||||
|
||||
@ -3,11 +3,14 @@ image:
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- WITH_NO_EXCEPTIONS: OFF
|
||||
- CONFIGURATION: Debug
|
||||
WITH_NO_EXCEPTIONS: OFF
|
||||
WITH_CPP_LATEST: OFF
|
||||
- WITH_NO_EXCEPTIONS: ON
|
||||
- CONFIGURATION: Debug
|
||||
WITH_NO_EXCEPTIONS: ON
|
||||
WITH_CPP_LATEST: OFF
|
||||
- WITH_NO_EXCEPTIONS: OFF
|
||||
- CONFIGURATION: Release
|
||||
WITH_NO_EXCEPTIONS: OFF
|
||||
WITH_CPP_LATEST: ON
|
||||
|
||||
configuration:
|
||||
|
||||
@ -38,13 +38,13 @@ PROJECT_NAME = Continuable
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 3.0.0
|
||||
PROJECT_NUMBER = 4.0.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_BRIEF = "C++14 asynchronous allocation aware futures"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
|
||||
@ -41,7 +41,7 @@ New helper functions were added to create ready continuables:
|
||||
|
||||
The implementation of connections were rewritten entirely.
|
||||
It is possible now to connect runtime sized containers as well as
|
||||
deeply nested sequences. See \ref tutorial-connections for details.
|
||||
deeply nested sequences. See \ref tutorial-connecting-continuables for details.
|
||||
|
||||
Additionally connection overloads were added that accept two iterators
|
||||
in order to come closer to the interface of the standard library.
|
||||
|
||||
@ -34,6 +34,7 @@ in order to change the libraries behaviour:
|
||||
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
|
||||
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
|
||||
| `CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK` | Allows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers. |
|
||||
| `CONTINUABLE_WITH_IMMEDIATE_TYPES` | Don't decorate the used type erasure, which is done to keep type names minimal for better error messages in debug builds. |
|
||||
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
|
||||
|
||||
*/
|
||||
|
||||
@ -123,19 +123,31 @@ public:
|
||||
std::enable_if_t<detail::base::can_accept_continuation<
|
||||
Data, Annotation,
|
||||
detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
|
||||
continuable_base(OtherData&& data)
|
||||
/* implicit */ continuable_base(OtherData&& data)
|
||||
: data_(detail::base::proxy_continuable<
|
||||
Annotation, detail::traits::unrefcv_t<OtherData>>(
|
||||
std::forward<OtherData>(data))) {
|
||||
}
|
||||
|
||||
/// Constructor taking the data of other continuable_base objects
|
||||
/// while erasing the hint.
|
||||
///
|
||||
/// This constructor makes it possible to replace the internal data object of
|
||||
/// the continuable by any object which is useful for type-erasure.
|
||||
/*template <typename OData,
|
||||
std::enable_if_t<std::is_convertible<
|
||||
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
||||
continuable_base(continuable_base<OData, Annotation>&& other)
|
||||
: continuable_base(std::move(other).consume()) {
|
||||
}*/
|
||||
|
||||
/// Constructor taking the data of other continuable_base objects
|
||||
/// while erasing the hint.
|
||||
///
|
||||
/// This constructor makes it possible to replace the internal data object of
|
||||
/// the continuable by any object which is useful for type-erasure.
|
||||
template <typename OData, typename OAnnotation>
|
||||
continuable_base(continuable_base<OData, OAnnotation>&& other)
|
||||
/* implicit */ continuable_base(continuable_base<OData, OAnnotation>&& other)
|
||||
: continuable_base(std::move(other).finish().consume()) {
|
||||
}
|
||||
|
||||
@ -853,7 +865,7 @@ constexpr auto make_continuable(Continuation&& continuation) {
|
||||
template <typename... Args>
|
||||
auto make_ready_continuable(Args&&... args) {
|
||||
using detail::base::ready_continuation;
|
||||
using detail::traits::identity;
|
||||
using detail::identity;
|
||||
using detail::traits::unrefcv_t;
|
||||
return detail::base::attorney::create_from_raw(
|
||||
ready_continuation<unrefcv_t<Args>...>{std::forward<Args>(args)...},
|
||||
@ -932,7 +944,7 @@ auto make_cancelling_continuable() {
|
||||
/// // Recovered from the failure
|
||||
/// })
|
||||
/// ```
|
||||
/// A corresponding \ref result is returned by \ref recover:
|
||||
/// A corresponding \ref result is returned by \ref recover
|
||||
/// ```cpp
|
||||
/// http_request("example.com")
|
||||
/// .then([](std::string content) -> cti::result<int, int> {
|
||||
|
||||
@ -51,7 +51,7 @@ namespace std {
|
||||
namespace experimental {
|
||||
template <typename Data, typename... Args, typename... FunctionArgs>
|
||||
struct coroutine_traits<
|
||||
cti::continuable_base<Data, cti::detail::traits::identity<Args...>>,
|
||||
cti::continuable_base<Data, cti::detail::identity<Args...>>,
|
||||
FunctionArgs...> {
|
||||
|
||||
using promise_type =
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#define CONTINUABLE_PRIMITIVES_HPP_INCLUDED
|
||||
|
||||
#include <continuable/detail/core/types.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
namespace cti {
|
||||
/// \defgroup Primitives Primitives
|
||||
@ -50,12 +51,19 @@ namespace cti {
|
||||
/// ```cpp
|
||||
/// template<typename... Args>
|
||||
/// struct callback {
|
||||
/// void operator() (Args...);
|
||||
/// void operator() (cti::exception_arg_t, cti::exception_t);
|
||||
/// void operator() (Args...) &&;
|
||||
/// void operator() (cti::exception_arg_t, cti::exception_t) &&;
|
||||
/// };
|
||||
/// ```
|
||||
/// \{
|
||||
|
||||
/// Represents the tag type that is used to specify the signature hint
|
||||
/// of a continuable_base or promise_base.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
template <typename... Args>
|
||||
using signature_arg_t = detail::identity<Args...>;
|
||||
|
||||
/// Represents the tag type that is used to query the continuation
|
||||
/// for whether it resolves the callback instantly with its arguments
|
||||
/// without having side effects.
|
||||
@ -69,7 +77,7 @@ struct is_ready_arg_t {};
|
||||
/// It's required that the query of is_ready_arg_t returns true.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
struct query_arg_t {};
|
||||
struct query_arg_t { };
|
||||
|
||||
/// Represents the tag type that is used to disambiguate the
|
||||
/// callback operator() in order to take the exception asynchronous chain.
|
||||
@ -87,7 +95,7 @@ struct exception_arg_t {};
|
||||
///
|
||||
[[deprecated("The dispatch_error_tag was replaced by exception_arg_t and will "
|
||||
"be removed in a later major version!")]] //
|
||||
typedef exception_arg_t dispatch_error_tag;
|
||||
typedef exception_arg_t dispatch_error_tag;
|
||||
|
||||
/// Represents the type that is used as exception type
|
||||
///
|
||||
@ -108,7 +116,7 @@ using exception_t = detail::types::exception_t;
|
||||
///
|
||||
[[deprecated("The error_type was replaced by exception_t and will "
|
||||
"be removed in a later major version!")]] //
|
||||
typedef exception_t error_type;
|
||||
typedef exception_t error_type;
|
||||
/// \}
|
||||
} // namespace cti
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include <continuable/continuable-primitives.hpp>
|
||||
#include <continuable/detail/core/annotation.hpp>
|
||||
#include <continuable/detail/core/types.hpp>
|
||||
#include <continuable/detail/utility/traits.hpp>
|
||||
#include <continuable/detail/utility/util.hpp>
|
||||
|
||||
namespace cti {
|
||||
@ -62,7 +63,7 @@ class promise_base
|
||||
/// \cond false
|
||||
;
|
||||
template <typename Data, typename... Args>
|
||||
class promise_base<Data, detail::traits::identity<Args...>>
|
||||
class promise_base<Data, detail::identity<Args...>>
|
||||
: detail::util::non_copyable
|
||||
/// \endcond
|
||||
{ // clang-format on
|
||||
@ -83,8 +84,9 @@ public:
|
||||
/// \endcond
|
||||
|
||||
/// Constructor accepting any object convertible to the data object
|
||||
template <typename OData, std::enable_if_t<std::is_convertible<
|
||||
std::decay_t<OData>, Data>::value>* = nullptr>
|
||||
template <typename OData,
|
||||
std::enable_if_t<std::is_convertible<
|
||||
detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
|
||||
promise_base(OData&& data) : data_(std::forward<OData>(data)) {
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +158,7 @@
|
||||
/// \since 1.0.0
|
||||
#define ASSERT_ASYNC_TYPES(CONTINUABLE, ...) \
|
||||
cti::detail::testing::assert_async_types( \
|
||||
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
||||
CONTINUABLE, cti::detail::identity<__VA_ARGS__>{})
|
||||
|
||||
/// Asserts that the continuable is finished with the given exception
|
||||
///
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||
#define CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <continuable/continuable-base.hpp>
|
||||
#include <continuable/continuable-primitives.hpp>
|
||||
#include <continuable/continuable-promise-base.hpp>
|
||||
#include <continuable/detail/core/annotation.hpp>
|
||||
#include <continuable/detail/core/types.hpp>
|
||||
|
||||
namespace cti {
|
||||
/// \defgroup Types Types
|
||||
/// provides the \link cti::continuable continuable\endlink and \link
|
||||
/// cti::promise promise\endlink facility for type erasure.
|
||||
/// \{
|
||||
|
||||
/// Trait to retrieve a continuable_base type with a given type-erasure backend.
|
||||
///
|
||||
/// Every object may me used as type-erasure backend as long as the
|
||||
/// requirements of a `std::function` like wrapper are satisfied.
|
||||
///
|
||||
/// \tparam CallbackWrapper The type which is used to erase the callback.
|
||||
///
|
||||
/// \tparam ContinuationWrapper The type which is used to erase the
|
||||
/// continuation data.
|
||||
///
|
||||
/// \tparam Args The current signature of the continuable.
|
||||
template <template <std::size_t, typename...> class CallbackWrapper,
|
||||
template <std::size_t, typename...> class ContinuationWrapper,
|
||||
typename... Args>
|
||||
class continuable_trait {
|
||||
|
||||
using callback = CallbackWrapper<0U, void(Args...)&&,
|
||||
void(exception_arg_t, exception_t) &&>;
|
||||
|
||||
public:
|
||||
/// The promise type which is used to resolve continuations
|
||||
using promise = promise_base<callback, detail::traits::identity<Args...>>;
|
||||
|
||||
/// The continuable type for the given parameters.
|
||||
using continuable = continuable_base<
|
||||
ContinuationWrapper<
|
||||
// Size the buffer for the small functor optimization so the
|
||||
// result itself fits in and guarantee that a pointer can
|
||||
// fit in as well.
|
||||
(sizeof(detail::base::ready_continuation<Args...>) < sizeof(void*)
|
||||
? sizeof(void*)
|
||||
: sizeof(detail::base::ready_continuation<Args...>)),
|
||||
void(promise), //
|
||||
bool(is_ready_arg_t) const, //
|
||||
std::tuple<Args...>(query_arg_t) //
|
||||
>,
|
||||
detail::traits::identity<Args...>>;
|
||||
};
|
||||
/// \}
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_TRAIT_HPP_INCLUDED
|
||||
@ -31,9 +31,11 @@
|
||||
#ifndef CONTINUABLE_TYPES_HPP_INCLUDED
|
||||
#define CONTINUABLE_TYPES_HPP_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <function2/function2.hpp>
|
||||
#include <continuable/continuable-trait.hpp>
|
||||
#include <continuable/continuable-base.hpp>
|
||||
#include <continuable/continuable-primitives.hpp>
|
||||
#include <continuable/continuable-promise-base.hpp>
|
||||
#include <continuable/detail/other/erasure.hpp>
|
||||
|
||||
namespace cti {
|
||||
/// \defgroup Types Types
|
||||
@ -41,57 +43,65 @@ namespace cti {
|
||||
/// cti::promise promise\endlink facility for type erasure.
|
||||
/// \{
|
||||
|
||||
// clang-format off
|
||||
namespace detail {
|
||||
/// A function which isn't size adjusted and move only
|
||||
template<std::size_t, typename... Args>
|
||||
using unique_function_adapter = fu2::unique_function<Args...>;
|
||||
/// A function which is size adjusted and move only
|
||||
template<std::size_t Size, typename... Args>
|
||||
using unique_function_adjustable = fu2::function_base<true, false, Size,
|
||||
true, false, Args...>;
|
||||
|
||||
/// We adjust the internal capacity of the outer function wrapper so
|
||||
/// we don't have to allocate twice when using `continuable<...>`.
|
||||
template<typename... Args>
|
||||
using unique_trait_of = continuable_trait<
|
||||
unique_function_adapter,
|
||||
unique_function_adjustable,
|
||||
Args...
|
||||
>;
|
||||
|
||||
/// A type erasure for work objects
|
||||
using work = fu2::unique_function<void()>;
|
||||
} // namespace detail
|
||||
/// Deduces to the preferred continuation capacity for a possible
|
||||
/// small functor optimization. The given capacity size is always enough to
|
||||
/// to avoid any allocation when storing a ready continuable_base.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
template <typename... Args>
|
||||
using continuation_capacity = detail::erasure::continuation_capacity<Args...>;
|
||||
|
||||
/// Defines a non-copyable continuation type which uses the
|
||||
/// function2 backend for type erasure.
|
||||
///
|
||||
/// Usable like: `continuable<int, float>`
|
||||
///
|
||||
/// \note You can always define your own continuable with a type erasure of
|
||||
/// choice, the type erasure wrapper just needs to accept a
|
||||
/// callable object with a continuation signature as specified
|
||||
/// in the Primitives section.
|
||||
///
|
||||
/// \since 1.0.0
|
||||
template <typename... Args>
|
||||
using continuable = typename detail::unique_trait_of<
|
||||
Args...
|
||||
>::continuable;
|
||||
using continuable = continuable_base<detail::erasure::continuation<Args...>, //
|
||||
signature_arg_t<Args...>>;
|
||||
|
||||
/// Defines a non-copyable promise type which is using the
|
||||
/// function2 backend for type erasure.
|
||||
///
|
||||
/// Usable like: `promise<int, float>`
|
||||
///
|
||||
/// \note You can always define your own promise with a type erasure of
|
||||
/// choice, the type erasure wrapper just needs to accept a
|
||||
/// callable object with a callback signature as specified
|
||||
/// in the Primitives section.
|
||||
///
|
||||
/// \since 1.0.0
|
||||
template <typename... Args>
|
||||
using promise = typename detail::unique_trait_of<
|
||||
Args...
|
||||
>::promise;
|
||||
using promise = promise_base<detail::erasure::callback<Args...>, //
|
||||
signature_arg_t<Args...>>;
|
||||
|
||||
/// Defines a non-copyable type erasure which is capable of carrying
|
||||
/// callable objects passed to executors.
|
||||
///
|
||||
/// \note You can always define your own work with a type erasure of
|
||||
/// choice, the type erasure wrapper just needs to accept a
|
||||
/// callable object which is callable with a `void()` signature.
|
||||
///
|
||||
/// \since 4.0.0
|
||||
using work = detail::work;
|
||||
class work : public fu2::unique_function<void()> {
|
||||
public:
|
||||
work() = default;
|
||||
~work() = default;
|
||||
work(work const&) = delete;
|
||||
work(work&&) = default;
|
||||
work& operator=(work const&) = delete;
|
||||
work& operator=(work&&) = default;
|
||||
|
||||
// TODO channel
|
||||
// TODO sink
|
||||
|
||||
// clang-format on
|
||||
using fu2::unique_function<void()>::unique_function;
|
||||
using fu2::unique_function<void()>::operator=;
|
||||
using fu2::unique_function<void()>::operator();
|
||||
};
|
||||
/// \}
|
||||
} // namespace cti
|
||||
|
||||
|
||||
@ -52,7 +52,6 @@ namespace cti {}
|
||||
#include <continuable/continuable-promise-base.hpp>
|
||||
#include <continuable/continuable-promisify.hpp>
|
||||
#include <continuable/continuable-result.hpp>
|
||||
#include <continuable/continuable-trait.hpp>
|
||||
#include <continuable/continuable-transforms.hpp>
|
||||
#include <continuable/continuable-traverse-async.hpp>
|
||||
#include <continuable/continuable-traverse.hpp>
|
||||
|
||||
@ -75,13 +75,13 @@ T&& unpack_lazy(container::flat_variant<T>&& value) {
|
||||
template <typename Continuable>
|
||||
class continuable_box;
|
||||
template <typename Data>
|
||||
class continuable_box<continuable_base<Data, traits::identity<>>> {
|
||||
class continuable_box<continuable_base<Data, identity<>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<>> continuable_;
|
||||
continuable_base<Data, identity<>> continuable_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<>>&& continuable)
|
||||
continuable_base<Data, identity<>>&& continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
|
||||
@ -101,14 +101,14 @@ public:
|
||||
}
|
||||
};
|
||||
template <typename Data, typename First>
|
||||
class continuable_box<continuable_base<Data, traits::identity<First>>> {
|
||||
class continuable_box<continuable_base<Data, identity<First>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<First>> continuable_;
|
||||
continuable_base<Data, identity<First>> continuable_;
|
||||
lazy_value_t<First> first_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<First>>&& continuable)
|
||||
continuable_base<Data, identity<First>>&& continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
|
||||
@ -130,14 +130,14 @@ public:
|
||||
};
|
||||
template <typename Data, typename First, typename Second, typename... Rest>
|
||||
class continuable_box<
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>>> {
|
||||
continuable_base<Data, identity<First, Second, Rest...>>> {
|
||||
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>> continuable_;
|
||||
continuable_base<Data, identity<First, Second, Rest...>> continuable_;
|
||||
lazy_value_t<std::tuple<First, Second, Rest...>> args_;
|
||||
|
||||
public:
|
||||
explicit continuable_box(
|
||||
continuable_base<Data, traits::identity<First, Second, Rest...>>&&
|
||||
continuable_base<Data, identity<First, Second, Rest...>>&&
|
||||
continuable)
|
||||
: continuable_(std::move(continuable)) {
|
||||
}
|
||||
@ -209,12 +209,12 @@ constexpr auto unbox_continuables(Args&&... args) {
|
||||
|
||||
namespace detail {
|
||||
template <typename Callback, typename Data>
|
||||
constexpr auto finalize_impl(traits::identity<void>, Callback&& callback,
|
||||
constexpr auto finalize_impl(identity<void>, Callback&& callback,
|
||||
Data&&) {
|
||||
return std::forward<Callback>(callback)();
|
||||
}
|
||||
template <typename... Args, typename Callback, typename Data>
|
||||
constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||
constexpr auto finalize_impl(identity<std::tuple<Args...>>,
|
||||
Callback&& callback, Data&& data) {
|
||||
// Call the final callback with the cleaned result
|
||||
return traits::unpack(std::forward<Callback>(callback),
|
||||
@ -223,7 +223,7 @@ constexpr auto finalize_impl(traits::identity<std::tuple<Args...>>,
|
||||
|
||||
struct hint_mapper {
|
||||
template <typename... T>
|
||||
constexpr auto operator()(T...) -> traits::identity<T...> {
|
||||
constexpr auto operator()(T...) -> identity<T...> {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
@ -233,7 +233,7 @@ template <typename Callback, typename Data>
|
||||
constexpr auto finalize_data(Callback&& callback, Data&& data) {
|
||||
using result_t = decltype(unbox_continuables(std::forward<Data>(data)));
|
||||
// Guard the final result against void
|
||||
return detail::finalize_impl(traits::identity<std::decay_t<result_t>>{},
|
||||
return detail::finalize_impl(identity<std::decay_t<result_t>>{},
|
||||
std::forward<Callback>(callback),
|
||||
std::forward<Data>(data));
|
||||
}
|
||||
|
||||
@ -88,30 +88,30 @@ private:
|
||||
|
||||
struct result_deducer {
|
||||
template <typename T>
|
||||
static auto deduce_one(std::false_type, traits::identity<T>) {
|
||||
static auto deduce_one(std::false_type, identity<T>) {
|
||||
static_assert(traits::fail<T>::value,
|
||||
"Non continuable types except tuple like and homogeneous "
|
||||
"containers aren't allowed inside an any expression!");
|
||||
}
|
||||
template <typename T>
|
||||
static auto deduce_one(std::true_type, traits::identity<T> id) {
|
||||
static auto deduce_one(std::true_type, identity<T> id) {
|
||||
return base::annotation_of(id);
|
||||
}
|
||||
template <typename T>
|
||||
static auto deduce(traversal::container_category_tag<false, false>,
|
||||
traits::identity<T> id) {
|
||||
identity<T> id) {
|
||||
return deduce_one<T>(base::is_continuable<T>{}, id);
|
||||
}
|
||||
|
||||
/// Deduce a homogeneous container
|
||||
template <bool IsTupleLike, typename T>
|
||||
static auto deduce(traversal::container_category_tag<true, IsTupleLike>,
|
||||
traits::identity<T>) {
|
||||
identity<T>) {
|
||||
|
||||
// Deduce the containing type
|
||||
using element_t = std::decay_t<decltype(*std::declval<T>().begin())>;
|
||||
return deduce(traversal::container_category_of_t<element_t>{},
|
||||
traits::identity<element_t>{});
|
||||
identity<element_t>{});
|
||||
}
|
||||
|
||||
template <typename First, typename... T>
|
||||
@ -125,19 +125,19 @@ struct result_deducer {
|
||||
|
||||
template <std::size_t... I, typename T>
|
||||
static auto deduce_tuple_like(std::integer_sequence<std::size_t, I...>,
|
||||
traits::identity<T>) {
|
||||
identity<T>) {
|
||||
|
||||
return deduce_same_hints(deduce(
|
||||
traversal::container_category_of_t<
|
||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{},
|
||||
traits::identity<
|
||||
identity<
|
||||
std::decay_t<decltype(std::get<I>(std::declval<T>()))>>{})...);
|
||||
}
|
||||
|
||||
/// Traverse tuple like container
|
||||
template <typename T>
|
||||
static auto deduce(traversal::container_category_tag<false, true>,
|
||||
traits::identity<T> id) {
|
||||
identity<T> id) {
|
||||
|
||||
constexpr auto const size = std::tuple_size<T>::value;
|
||||
return deduce_tuple_like(std::make_index_sequence<size>{}, id);
|
||||
@ -172,7 +172,7 @@ struct connection_finalizer<connection_strategy_any_tag> {
|
||||
static auto finalize(Connection&& connection, util::ownership ownership) {
|
||||
constexpr auto const signature = decltype(any::result_deducer::deduce(
|
||||
traversal::container_category_of_t<std::decay_t<Connection>>{},
|
||||
traits::identity<std::decay_t<Connection>>{})){};
|
||||
identity<std::decay_t<Connection>>{})){};
|
||||
|
||||
return base::attorney::create_from(
|
||||
[connection =
|
||||
|
||||
@ -42,7 +42,7 @@ struct annotation_trait;
|
||||
|
||||
/// Specialization for a present signature hint
|
||||
template <typename... Args>
|
||||
struct annotation_trait<traits::identity<Args...>> {
|
||||
struct annotation_trait<identity<Args...>> {
|
||||
template <typename Continuable>
|
||||
static Continuable&& finish(Continuable&& continuable) {
|
||||
return std::forward<Continuable>(continuable);
|
||||
@ -55,9 +55,9 @@ namespace hints {
|
||||
///
|
||||
/// This is the overload taking an arbitrary amount of args
|
||||
template <typename... HintArgs>
|
||||
struct from_args : std::common_type<traits::identity<HintArgs...>> {};
|
||||
struct from_args : std::common_type<identity<HintArgs...>> {};
|
||||
template <>
|
||||
struct from_args<void> : std::common_type<traits::identity<>> {};
|
||||
struct from_args<void> : std::common_type<identity<>> {};
|
||||
} // namespace hints
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
@ -122,8 +122,7 @@ struct ready_continuation<> {
|
||||
template <typename Hint, typename Continuation>
|
||||
struct proxy_continuable;
|
||||
template <typename... Args, typename Continuation>
|
||||
struct proxy_continuable<traits::identity<Args...>, Continuation>
|
||||
: Continuation {
|
||||
struct proxy_continuable<identity<Args...>, Continuation> : Continuation {
|
||||
|
||||
explicit proxy_continuable(Continuation continuation)
|
||||
: Continuation(std::move(continuation)) {
|
||||
@ -192,9 +191,9 @@ struct attorney {
|
||||
|
||||
/// Returns the signature hint of the given continuable
|
||||
template <typename Data, typename... Args>
|
||||
constexpr traits::identity<Args...>
|
||||
annotation_of(traits::identity<continuable_base<Data, //
|
||||
traits::identity<Args...>>>) {
|
||||
constexpr identity<Args...>
|
||||
annotation_of(identity<continuable_base<Data, //
|
||||
identity<Args...>>>) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -275,30 +274,28 @@ constexpr void invoke_no_except(T&& callable, Args&&... args) noexcept {
|
||||
}
|
||||
|
||||
template <typename... Args, typename T>
|
||||
void invoke_void_no_except(traits::identity<exception_arg_t, Args...>,
|
||||
void invoke_void_no_except(identity<exception_arg_t, Args...>,
|
||||
T&& /*callable*/) noexcept {
|
||||
// Don't invoke the next failure handler when being in an exception handler
|
||||
}
|
||||
template <typename... Args, typename T>
|
||||
void invoke_void_no_except(traits::identity<Args...>, T&& callable) noexcept {
|
||||
void invoke_void_no_except(identity<Args...>, T&& callable) noexcept {
|
||||
std::forward<T>(callable)();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto make_invoker(T&& invoke, traits::identity<Args...>) {
|
||||
return invoker<std::decay_t<T>, traits::identity<Args...>>(
|
||||
std::forward<T>(invoke));
|
||||
constexpr auto make_invoker(T&& invoke, identity<Args...>) {
|
||||
return invoker<std::decay_t<T>, identity<Args...>>(std::forward<T>(invoke));
|
||||
}
|
||||
|
||||
/// - continuable<?...> -> result(next_callback);
|
||||
template <typename Data, typename Annotation>
|
||||
constexpr auto
|
||||
invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||
constexpr auto invoker_of(identity<continuable_base<Data, Annotation>>) {
|
||||
/// Get the hint of the unwrapped returned continuable
|
||||
using Type =
|
||||
decltype(std::declval<continuable_base<Data, Annotation>>().finish());
|
||||
|
||||
auto constexpr const hint = base::annotation_of(traits::identify<Type>{});
|
||||
auto constexpr const hint = base::annotation_of(identify<Type>{});
|
||||
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
@ -317,7 +314,7 @@ invoker_of(traits::identity<continuable_base<Data, Annotation>>) {
|
||||
|
||||
/// - ? -> next_callback(?)
|
||||
template <typename T>
|
||||
constexpr auto invoker_of(traits::identity<T>) {
|
||||
constexpr auto invoker_of(identity<T>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -329,26 +326,26 @@ constexpr auto invoker_of(traits::identity<T>) {
|
||||
std::move(result));
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identify<T>{});
|
||||
identify<T>{});
|
||||
}
|
||||
|
||||
/// - void -> next_callback()
|
||||
inline auto invoker_of(traits::identity<void>) {
|
||||
inline auto invoker_of(identity<void>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
invoke_callback(std::forward<decltype(callback)>(callback),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
invoke_void_no_except(
|
||||
traits::identity<traits::unrefcv_t<decltype(args)>...>{},
|
||||
identity<traits::unrefcv_t<decltype(args)>...>{},
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - empty_result -> <cancel>
|
||||
inline auto invoker_of(traits::identity<empty_result>) {
|
||||
inline auto invoker_of(identity<empty_result>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
(void)next_callback;
|
||||
@ -362,11 +359,11 @@ inline auto invoker_of(traits::identity<empty_result>) {
|
||||
(void)result;
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - exceptional_result -> <throw>
|
||||
inline auto invoker_of(traits::identity<exceptional_result>) {
|
||||
inline auto invoker_of(identity<exceptional_result>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
util::unused(callback, next_callback, args...);
|
||||
@ -381,12 +378,12 @@ inline auto invoker_of(traits::identity<exceptional_result>) {
|
||||
std::move(result).get_exception());
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<>{});
|
||||
identity<>{});
|
||||
}
|
||||
|
||||
/// - result<?...> -> next_callback(?...)
|
||||
template <typename... Args>
|
||||
auto invoker_of(traits::identity<result<Args...>>) {
|
||||
auto invoker_of(identity<result<Args...>>) {
|
||||
return make_invoker(
|
||||
[](auto&& callback, auto&& next_callback, auto&&... args) {
|
||||
CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -416,7 +413,7 @@ auto invoker_of(traits::identity<result<Args...>>) {
|
||||
// asynchronous chain.
|
||||
CONTINUABLE_BLOCK_TRY_END
|
||||
},
|
||||
traits::identity<Args...>{});
|
||||
identity<Args...>{});
|
||||
}
|
||||
|
||||
/// Returns a sequenced invoker which is able to invoke
|
||||
@ -443,15 +440,14 @@ inline auto sequenced_unpack_invoker() {
|
||||
|
||||
// - std::pair<?, ?> -> next_callback(?, ?)
|
||||
template <typename First, typename Second>
|
||||
constexpr auto invoker_of(traits::identity<std::pair<First, Second>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(),
|
||||
traits::identity<First, Second>{});
|
||||
constexpr auto invoker_of(identity<std::pair<First, Second>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(), identity<First, Second>{});
|
||||
}
|
||||
|
||||
// - std::tuple<?...> -> next_callback(?...)
|
||||
template <typename... Args>
|
||||
constexpr auto invoker_of(traits::identity<std::tuple<Args...>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(), traits::identity<Args...>{});
|
||||
constexpr auto invoker_of(identity<std::tuple<Args...>>) {
|
||||
return make_invoker(sequenced_unpack_invoker(), identity<Args...>{});
|
||||
}
|
||||
|
||||
#undef CONTINUABLE_BLOCK_TRY_BEGIN
|
||||
@ -511,24 +507,20 @@ namespace proto {
|
||||
template <handle_results HandleResults, typename Base, typename Hint>
|
||||
struct result_handler_base;
|
||||
template <typename Base, typename... Args>
|
||||
struct result_handler_base<handle_results::no, Base,
|
||||
traits::identity<Args...>> {
|
||||
struct result_handler_base<handle_results::no, Base, identity<Args...>> {
|
||||
void operator()(Args... args) && {
|
||||
// Forward the arguments to the next callback
|
||||
std::move(static_cast<Base*>(this)->next_callback_)(std::move(args)...);
|
||||
}
|
||||
};
|
||||
template <typename Base, typename... Args>
|
||||
struct result_handler_base<handle_results::yes, Base,
|
||||
traits::identity<Args...>> {
|
||||
struct result_handler_base<handle_results::yes, Base, identity<Args...>> {
|
||||
/// The operator which is called when the result was provided
|
||||
void operator()(Args... args) && {
|
||||
// In order to retrieve the correct decorator we must know what the
|
||||
// result type is.
|
||||
constexpr auto result =
|
||||
traits::identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_),
|
||||
std::move(args)...))>{};
|
||||
constexpr auto result = identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_), std::move(args)...))>{};
|
||||
|
||||
// Pick the correct invoker that handles decorating of the result
|
||||
auto invoker = decoration::invoker_of(result);
|
||||
@ -557,10 +549,9 @@ template <typename Base>
|
||||
struct error_handler_base<handle_errors::forward, Base> {
|
||||
/// The operator which is called when an error occurred
|
||||
void operator()(exception_arg_t, exception_t exception) && {
|
||||
constexpr auto result =
|
||||
traits::identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_), exception_arg_t{},
|
||||
std::move(exception)))>{};
|
||||
constexpr auto result = identify<decltype(decoration::invoke_callback(
|
||||
std::move(static_cast<Base*>(this)->callback_), exception_arg_t{},
|
||||
std::move(exception)))>{};
|
||||
|
||||
auto invoker = decoration::invoker_of(result);
|
||||
|
||||
@ -582,16 +573,16 @@ struct callback_base;
|
||||
template <typename... Args, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor,
|
||||
typename NextCallback>
|
||||
struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>
|
||||
struct callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||
Executor, NextCallback>
|
||||
: proto::result_handler_base<
|
||||
HandleResults,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>,
|
||||
traits::identity<Args...>>,
|
||||
identity<Args...>>,
|
||||
proto::error_handler_base<
|
||||
HandleErrors,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>>,
|
||||
util::non_copyable {
|
||||
|
||||
@ -608,15 +599,15 @@ struct callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
/// Pull the result handling operator() in
|
||||
using proto::result_handler_base<
|
||||
HandleResults,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>,
|
||||
traits::identity<Args...>>::operator();
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||
Executor, NextCallback>,
|
||||
identity<Args...>>::operator();
|
||||
|
||||
/// Pull the error handling operator() in
|
||||
using proto::error_handler_base<
|
||||
HandleErrors,
|
||||
callback_base<traits::identity<Args...>, HandleResults, HandleErrors,
|
||||
Callback, Executor, NextCallback>>::operator();
|
||||
callback_base<identity<Args...>, HandleResults, HandleErrors, Callback,
|
||||
Executor, NextCallback>>::operator();
|
||||
|
||||
/// Resolves the continuation with the given values
|
||||
void set_value(Args... args) {
|
||||
@ -683,21 +674,19 @@ struct final_callback : util::non_copyable {
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto
|
||||
next_hint_of(std::integral_constant<handle_results, handle_results::yes>,
|
||||
traits::identity<T> /*callback*/,
|
||||
traits::identity<Args...> /*current*/) {
|
||||
identity<T> /*callback*/, identity<Args...> /*current*/) {
|
||||
// Partial Invoke the given callback
|
||||
using Result = decltype(
|
||||
decoration::invoke_callback(std::declval<T>(), std::declval<Args>()...));
|
||||
|
||||
// Return the hint of thr given invoker
|
||||
return decltype(decoration::invoker_of(traits::identify<Result>{}).hint()){};
|
||||
return decltype(decoration::invoker_of(identify<Result>{}).hint()){};
|
||||
}
|
||||
/// Don't progress the hint when we don't continue
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto
|
||||
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
|
||||
traits::identity<T> /*callback*/,
|
||||
traits::identity<Args...> current) {
|
||||
identity<T> /*callback*/, identity<Args...> current) {
|
||||
return current;
|
||||
}
|
||||
|
||||
@ -729,9 +718,9 @@ struct chained_continuation;
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Continuation, typename Callback,
|
||||
typename Executor>
|
||||
struct chained_continuation<traits::identity<Args...>,
|
||||
traits::identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, Continuation, Callback, Executor> {
|
||||
struct chained_continuation<identity<Args...>, identity<NextArgs...>,
|
||||
HandleResults, HandleErrors, Continuation, Callback,
|
||||
Executor> {
|
||||
|
||||
Continuation continuation_;
|
||||
Callback callback_;
|
||||
@ -760,8 +749,8 @@ struct chained_continuation<traits::identity<Args...>,
|
||||
// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||
// - Callback: [](std::string) { }
|
||||
// - NextCallback: []() { }
|
||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
||||
HandleResults, HandleErrors>(
|
||||
auto proxy = callbacks::make_callback<identity<Args...>, HandleResults,
|
||||
HandleErrors>(
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
|
||||
@ -791,9 +780,9 @@ struct chained_continuation<traits::identity<Args...>,
|
||||
// Specialization to unpack ready continuables directly
|
||||
template <typename... Args, typename... NextArgs, handle_results HandleResults,
|
||||
handle_errors HandleErrors, typename Callback, typename Executor>
|
||||
struct chained_continuation<
|
||||
traits::identity<Args...>, traits::identity<NextArgs...>, HandleResults,
|
||||
HandleErrors, ready_continuation<Args...>, Callback, Executor> {
|
||||
struct chained_continuation<identity<Args...>, identity<NextArgs...>,
|
||||
HandleResults, HandleErrors,
|
||||
ready_continuation<Args...>, Callback, Executor> {
|
||||
|
||||
ready_continuation<Args...> continuation_;
|
||||
Callback callback_;
|
||||
@ -814,8 +803,8 @@ struct chained_continuation<
|
||||
|
||||
template <typename NextCallback>
|
||||
void operator()(NextCallback&& next_callback) {
|
||||
auto proxy = callbacks::make_callback<traits::identity<Args...>,
|
||||
HandleResults, HandleErrors>(
|
||||
auto proxy = callbacks::make_callback<identity<Args...>, HandleResults,
|
||||
HandleErrors>(
|
||||
std::move(callback_), std::move(executor_),
|
||||
std::forward<decltype(next_callback)>(next_callback));
|
||||
|
||||
@ -850,10 +839,10 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||
static_assert(is_continuable<std::decay_t<Continuation>>{},
|
||||
"Expected a continuation!");
|
||||
|
||||
using Hint = decltype(base::annotation_of(traits::identify<Continuation>()));
|
||||
using Hint = decltype(base::annotation_of(identify<Continuation>()));
|
||||
constexpr auto next_hint =
|
||||
next_hint_of(std::integral_constant<handle_results, HandleResults>{},
|
||||
traits::identify<decltype(callback)>{}, Hint{});
|
||||
identify<decltype(callback)>{}, Hint{});
|
||||
|
||||
auto ownership = attorney::ownership_of(continuation);
|
||||
auto data =
|
||||
@ -875,7 +864,7 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
|
||||
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
|
||||
template <typename Data, typename... Args>
|
||||
void finalize_continuation(
|
||||
continuable_base<Data, traits::identity<Args...>>&& continuation) noexcept {
|
||||
continuable_base<Data, identity<Args...>>&& continuation) noexcept {
|
||||
#ifdef CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
|
||||
invoke_continuation(std::move(continuation),
|
||||
CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK<Args...>{});
|
||||
@ -890,13 +879,12 @@ void finalize_continuation(
|
||||
template <typename Data, typename Annotation, typename Continuation>
|
||||
struct can_accept_continuation : std::false_type {};
|
||||
template <typename Data, typename... Args, typename Continuation>
|
||||
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
|
||||
struct can_accept_continuation<Data, identity<Args...>, Continuation>
|
||||
: traits::conjunction<
|
||||
traits::is_invocable<Continuation,
|
||||
callbacks::final_callback<Args...>>,
|
||||
std::is_convertible<
|
||||
proxy_continuable<traits::identity<Args...>, Continuation>,
|
||||
Data>> {};
|
||||
proxy_continuable<identity<Args...>, Continuation>, Data>> {};
|
||||
|
||||
/// Workaround for GCC bug:
|
||||
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
#include <utility>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
|
||||
#ifndef CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||
|
||||
@ -106,6 +106,18 @@
|
||||
#else
|
||||
#undef CONTINUABLE_HAS_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
/// Define CONTINUABLE_HAS_IMMEDIATE_TYPES when either
|
||||
/// - CONTINUABLE_WITH_IMMEDIATE_TYPES is defined
|
||||
/// - Building in release mode (NDEBUG is defined)
|
||||
///
|
||||
/// Build error messages will become more readable in debug mode while
|
||||
/// we don't suffer any runtime penalty in release.
|
||||
#if defined(CONTINUABLE_WITH_IMMEDIATE_TYPES) || defined(NDEBUG)
|
||||
#define CONTINUABLE_HAS_IMMEDIATE_TYPES 1
|
||||
#else
|
||||
#undef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED
|
||||
|
||||
@ -57,7 +57,7 @@ using std::experimental::coroutine_handle;
|
||||
template <typename T>
|
||||
struct result_from_identity;
|
||||
template <typename... T>
|
||||
struct result_from_identity<traits::identity<T...>> {
|
||||
struct result_from_identity<identity<T...>> {
|
||||
using result_t = result<T...>;
|
||||
};
|
||||
|
||||
@ -65,7 +65,7 @@ struct result_from_identity<traits::identity<T...>> {
|
||||
/// for waiting on a continuable in a stackless coroutine.
|
||||
template <typename Continuable>
|
||||
class awaitable {
|
||||
using hint_t = decltype(base::annotation_of(traits::identify<Continuable>{}));
|
||||
using hint_t = decltype(base::annotation_of(identify<Continuable>{}));
|
||||
using result_t = typename result_from_identity<hint_t>::result_t;
|
||||
|
||||
/// The continuable which is invoked upon suspension
|
||||
|
||||
180
include/continuable/detail/other/erasure.hpp
Normal file
180
include/continuable/detail/other/erasure.hpp
Normal file
@ -0,0 +1,180 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
#define CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <function2/function2.hpp>
|
||||
#include <continuable/detail/core/base.hpp>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/traits.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
namespace erasure {
|
||||
template <typename... Args>
|
||||
using callback_erasure_t =
|
||||
fu2::function_base<true, false, fu2::capacity_none, true, false,
|
||||
void(Args...)&&, void(exception_arg_t, exception_t) &&>;
|
||||
|
||||
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||
template <typename... Args>
|
||||
using callback = callback_erasure_t<Args...>;
|
||||
#else
|
||||
template <typename... Args>
|
||||
class callback;
|
||||
|
||||
template <typename T>
|
||||
struct is_callback : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_callback<callback<Args...>> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
class callback : public callback_erasure_t<Args...> {
|
||||
public:
|
||||
using erasure_t = callback_erasure_t<Args...>;
|
||||
erasure_t erasure_;
|
||||
|
||||
callback() = default;
|
||||
~callback() = default;
|
||||
callback(callback const&) = delete;
|
||||
callback(callback&&) = default;
|
||||
callback& operator=(callback const&) = delete;
|
||||
callback& operator=(callback&&) = default;
|
||||
|
||||
template <
|
||||
typename T,
|
||||
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
||||
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
||||
/* implicit */ callback(T&& callable) : erasure_(std::forward<T>(callable)) {
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
||||
std::enable_if_t<!is_callback<traits::unrefcv_t<T>>::value>* = nullptr>
|
||||
callback& operator=(T&& callable) {
|
||||
erasure_ = std::forward<T>(callable);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator()(Args... args) && {
|
||||
std::move(erasure_)(std::move(args)...);
|
||||
}
|
||||
|
||||
void operator()(exception_arg_t exception_arg, exception_t exception) && {
|
||||
std::move(erasure_)(exception_arg, std::move(exception));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename... Args>
|
||||
struct continuation_capacity {
|
||||
using type = union {
|
||||
void* pointer_;
|
||||
base::ready_continuation<Args...> continuation_;
|
||||
};
|
||||
|
||||
static constexpr std::size_t capacity = sizeof(type);
|
||||
static constexpr std::size_t alignment = alignof(type);
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
using continuation_erasure_t = fu2::function_base<
|
||||
true, false, continuation_capacity<Args...>, true, false,
|
||||
void(promise_base<callback<Args...>, signature_arg_t<Args...>>),
|
||||
bool(is_ready_arg_t) const, std::tuple<Args...>(query_arg_t)>;
|
||||
|
||||
#ifdef CONTINUABLE_HAS_IMMEDIATE_TYPES
|
||||
template <typename... Args>
|
||||
using continuation = continuation_erasure_t<Args...>;
|
||||
#else
|
||||
template <typename... Args>
|
||||
class continuation;
|
||||
|
||||
template <typename T>
|
||||
struct is_continuation : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_continuation<continuation<Args...>> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
class continuation {
|
||||
using erasure_t = continuation_erasure_t<Args...>;
|
||||
erasure_t erasure_;
|
||||
|
||||
public:
|
||||
continuation() = default;
|
||||
~continuation() = default;
|
||||
continuation(continuation const&) = delete;
|
||||
continuation(continuation&&) = default;
|
||||
continuation& operator=(continuation const&) = delete;
|
||||
continuation& operator=(continuation&&) = default;
|
||||
|
||||
template <
|
||||
typename T,
|
||||
std::enable_if_t<std::is_convertible<T, erasure_t>::value>* = nullptr,
|
||||
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
||||
nullptr>
|
||||
/* implicit */ continuation(T&& callable)
|
||||
: erasure_(std::forward<T>(callable)) {
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
std::enable_if_t<std::is_assignable<erasure_t, T>::value>* = nullptr,
|
||||
std::enable_if_t<!is_continuation<traits::unrefcv_t<T>>::value>* =
|
||||
nullptr>
|
||||
continuation& operator=(T&& callable) {
|
||||
erasure_ = std::forward<T>(callable);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator()(promise_base<callback<Args...>, //
|
||||
signature_arg_t<Args...>>
|
||||
promise) {
|
||||
erasure_(std::move(promise));
|
||||
}
|
||||
|
||||
bool operator()(is_ready_arg_t is_ready_arg) const {
|
||||
return erasure_(is_ready_arg);
|
||||
}
|
||||
|
||||
std::tuple<Args...> operator()(query_arg_t query_arg) {
|
||||
return erasure_(query_arg);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace erasure
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_ERASURE_HPP_INCLUDED
|
||||
@ -179,15 +179,15 @@ template <typename... Expected>
|
||||
struct assert_async_types_validator {
|
||||
template <typename... Actual>
|
||||
void operator()(Actual...) {
|
||||
static_assert(std::is_same<traits::identity<Actual...>,
|
||||
traits::identity<Expected...>>::value,
|
||||
static_assert(std::is_same<identity<Actual...>,
|
||||
identity<Expected...>>::value,
|
||||
"The called arguments don't match with the expected ones!");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C, typename... Args>
|
||||
void assert_async_types(C&& continuable,
|
||||
traits::identity<Args...> /*expected*/) {
|
||||
identity<Args...> /*expected*/) {
|
||||
assert_async_validation(std::forward<C>(continuable),
|
||||
assert_async_types_validator<Args...>{});
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ template <typename Hint>
|
||||
class promise_callback;
|
||||
|
||||
template <typename... Args>
|
||||
class promise_callback<traits::identity<Args...>>
|
||||
class promise_callback<identity<Args...>>
|
||||
: public future_trait<Args...> {
|
||||
|
||||
typename future_trait<Args...>::promise_t promise_;
|
||||
@ -119,7 +119,7 @@ template <typename Data, typename Annotation>
|
||||
auto as_future(continuable_base<Data, Annotation>&& continuable) {
|
||||
// Create the promise which is able to supply the current arguments
|
||||
constexpr auto const hint =
|
||||
base::annotation_of(traits::identify<decltype(continuable)>{});
|
||||
base::annotation_of(identify<decltype(continuable)>{});
|
||||
|
||||
promise_callback<std::decay_t<decltype(hint)>> callback;
|
||||
(void)hint;
|
||||
|
||||
@ -62,7 +62,7 @@ template <typename T>
|
||||
using align_of_helper = std::integral_constant<std::size_t, alignof(T)>;
|
||||
|
||||
template <typename... T>
|
||||
constexpr auto storage_of_impl(traits::identity<T...>) {
|
||||
constexpr auto storage_of_impl(identity<T...>) {
|
||||
constexpr auto size = max_element_of({(size_of_helper<T>::value)...});
|
||||
constexpr auto align = max_element_of({(align_of_helper<T>::value)...});
|
||||
return std::aligned_storage_t<size, align>{};
|
||||
@ -70,7 +70,7 @@ constexpr auto storage_of_impl(traits::identity<T...>) {
|
||||
|
||||
/// Declares the aligned storage union for the given types
|
||||
template <typename... T>
|
||||
using storage_of_t = decltype(storage_of_impl(traits::identity<T...>{}));
|
||||
using storage_of_t = decltype(storage_of_impl(identity<T...>{}));
|
||||
|
||||
/// The value fpr the empty slot
|
||||
using slot_t = std::uint8_t;
|
||||
|
||||
54
include/continuable/detail/utility/identity.hpp
Normal file
54
include/continuable/detail/utility/identity.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
#define CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
#include <continuable/detail/features.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
/// A tagging type for wrapping other types
|
||||
template <typename... T>
|
||||
struct identity {};
|
||||
|
||||
template <typename>
|
||||
struct is_identity : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_identity<identity<Args...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||
identity<std::decay_t<T>>>;
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_IDENTITY_HPP_INCLUDED
|
||||
@ -36,6 +36,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <continuable/detail/features.hpp>
|
||||
#include <continuable/detail/utility/identity.hpp>
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
@ -69,19 +70,6 @@ auto make_flat_tuple(T&&... args) {
|
||||
return std::tuple<T...>{std::forward<T>(args)...};
|
||||
}
|
||||
|
||||
/// A tagging type for wrapping other types
|
||||
template <typename... T>
|
||||
struct identity {};
|
||||
|
||||
template <typename>
|
||||
struct is_identity : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_identity<identity<Args...>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
using identify = std::conditional_t<is_identity<std::decay_t<T>>::value, T,
|
||||
identity<std::decay_t<T>>>;
|
||||
|
||||
#if defined(CONTINUABLE_HAS_CXX17_VOID_T)
|
||||
using std::void_t;
|
||||
#else
|
||||
|
||||
@ -17,9 +17,11 @@ target_link_libraries(test-continuable-base
|
||||
|
||||
add_executable(test-continuable-single
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-connection-noinst
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-forward-decl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-flat-variant.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-result.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-promisify.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-erasure.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/single/test-continuable-traverse-async.cpp)
|
||||
|
||||
|
||||
@ -134,7 +134,7 @@ TYPED_TEST(single_dimension_tests, are_exceptions_partial_applyable) {
|
||||
handled = false;
|
||||
ASSERT_ASYNC_INCOMPLETION(
|
||||
this->supply_exception(supply_test_exception(),
|
||||
detail::traits::identity<int, int>{})
|
||||
detail::identity<int, int>{})
|
||||
.fail([&]() -> result<int, int> {
|
||||
EXPECT_FALSE(handled);
|
||||
handled = true;
|
||||
|
||||
89
test/unit-test/single/test-continuable-erasure.cpp
Normal file
89
test/unit-test/single/test-continuable-erasure.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
/*
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <test-continuable.hpp>
|
||||
|
||||
using namespace cti;
|
||||
|
||||
struct mypromise {
|
||||
void operator()() && {
|
||||
}
|
||||
|
||||
void operator()(exception_arg_t, exception_t) && {
|
||||
}
|
||||
};
|
||||
|
||||
struct my_continuation {
|
||||
template <typename Callback>
|
||||
void operator()(Callback&&) {
|
||||
}
|
||||
|
||||
bool operator()(is_ready_arg_t) const noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::tuple<> operator()(query_arg_t) {
|
||||
return std::make_tuple();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(single_erasure_test, is_assignable_from_promise) {
|
||||
detail::erasure::callback<> p(mypromise{});
|
||||
std::move(p)();
|
||||
}
|
||||
|
||||
TEST(single_erasure_test, is_assignable_from_continuation) {
|
||||
detail::erasure::continuation<> c(my_continuation{});
|
||||
ASSERT_TRUE(c(is_ready_arg_t{}));
|
||||
c(mypromise{});
|
||||
}
|
||||
|
||||
TEST(single_erasure_test, is_constructible_from_work) {
|
||||
bool flag = false;
|
||||
|
||||
work mywork([&] {
|
||||
EXPECT_FALSE(flag);
|
||||
flag = true;
|
||||
});
|
||||
|
||||
ASSERT_FALSE(flag);
|
||||
mywork();
|
||||
ASSERT_TRUE(flag);
|
||||
}
|
||||
|
||||
TEST(single_erasure_test, is_assignable_from_work) {
|
||||
bool flag = false;
|
||||
|
||||
work mywork;
|
||||
|
||||
mywork = [&] {
|
||||
EXPECT_FALSE(flag);
|
||||
flag = true;
|
||||
};
|
||||
|
||||
ASSERT_FALSE(flag);
|
||||
mywork();
|
||||
ASSERT_TRUE(flag);
|
||||
}
|
||||
31
test/unit-test/single/test-continuable-forward-decl.cpp
Normal file
31
test/unit-test/single/test-continuable-forward-decl.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
/*
|
||||
Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#include <test-continuable.hpp>
|
||||
|
||||
struct forward_decl_type_0;
|
||||
struct forward_decl_type_1;
|
||||
|
||||
cti::continuable<forward_decl_type_0> fails_not_with_forward_decls_1();
|
||||
cti::continuable<forward_decl_type_0, forward_decl_type_1>
|
||||
fails_not_with_forward_decls_2();
|
||||
@ -34,7 +34,7 @@
|
||||
#include <continuable/continuable-testing.hpp>
|
||||
#include <continuable/continuable.hpp>
|
||||
|
||||
using cti::detail::traits::identity;
|
||||
using cti::detail::identity;
|
||||
using cti::detail::util::unused;
|
||||
|
||||
inline auto to_hint(identity<> /*hint*/) {
|
||||
@ -48,7 +48,7 @@ auto to_hint(identity<Args...> hint) {
|
||||
template <typename... Args>
|
||||
auto supplier_of(Args&&... args) {
|
||||
return [values = std::make_tuple(std::forward<Args>(args)...)](
|
||||
auto&& promise) mutable {
|
||||
auto&& promise) mutable {
|
||||
cti::detail::traits::unpack(
|
||||
[&](auto&&... passed) {
|
||||
promise.set_value(std::forward<decltype(passed)>(passed)...);
|
||||
@ -113,12 +113,12 @@ struct provide_copyable {
|
||||
struct provide_unique {
|
||||
template <typename... Args, typename... Hint, typename T>
|
||||
auto make(identity<Args...>, identity<Hint...>, T&& callback) {
|
||||
return cti::make_continuable<Hint...>(
|
||||
[callback = std::forward<T>(callback),
|
||||
guard = std::make_unique<int>(0)](auto&&... args) mutable {
|
||||
(void)(*guard);
|
||||
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
return cti::make_continuable<Hint...>([
|
||||
callback = std::forward<T>(callback), guard = std::make_unique<int>(0)
|
||||
](auto&&... args) mutable {
|
||||
(void)(*guard);
|
||||
return std::move(callback)(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ function renew_build {
|
||||
# Configure the project and build it
|
||||
cmake -GNinja -DCMAKE_CXX_FLAGS="$STD_CXX_FLAGS $CMAKE_CXX_FLAGS -Werror" -DCMAKE_EXE_LINKER_FLAGS="$STD_LINKER_FLAGS" \
|
||||
-DCTI_CONTINUABLE_WITH_NO_EXCEPTIONS=$WITH_NO_EXCEPTIONS -DCTI_CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE=$WITH_AWAIT -DCTI_CONTINUABLE_WITH_LIGHT_TESTS=$WITH_LIGHT_TESTS \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug ..
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=$BUILD_CONFIG ..
|
||||
}
|
||||
|
||||
if [[ $CXX == *"clang"* ]]; then
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user