mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
more work on arg hints
This commit is contained in:
parent
b4a622047c
commit
6bd0b49064
@ -1 +1 @@
|
||||
Subproject commit ecd530865cefdfa7dea58e84f6aa1b548950363d
|
||||
Subproject commit 3447fc31b4eea1fbcb86fa0e2f5d9ed9f38776bf
|
||||
@ -127,7 +127,7 @@ template<typename...>
|
||||
struct deduce_to_void : std::common_type<void> { };
|
||||
|
||||
template<typename... T>
|
||||
using always_void_t = typename deduce_to_void<T...>::type;
|
||||
using void_t = typename deduce_to_void<T...>::type;
|
||||
|
||||
struct SelfDispatcher {
|
||||
template<typename T>
|
||||
@ -136,19 +136,21 @@ struct SelfDispatcher {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename... T>
|
||||
struct Identity { };
|
||||
|
||||
template<typename Config>
|
||||
class ContinuableBase;
|
||||
|
||||
template<typename T>
|
||||
void emptyContinuation(T&& callback) {
|
||||
std::forward<T>(callback)();
|
||||
inline auto emptyContinuation() {
|
||||
return [](auto&& callback) {
|
||||
std::forward<decltype(callback)>(callback)();
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void emptyCallback(Args&&... /*arguments*/) { }
|
||||
inline auto emptyCallback() {
|
||||
return [](auto&&...) { };
|
||||
}
|
||||
|
||||
template<typename S, unsigned... I, typename T, typename F>
|
||||
auto applyTuple(std::integer_sequence<S, I...>, T&& tuple, F&& function) {
|
||||
@ -189,14 +191,14 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ownership operator&& (Ownership right) const {
|
||||
Ownership operator&& (Ownership right) const noexcept {
|
||||
return Ownership(hasOwnership() && right.hasOwnership());
|
||||
}
|
||||
|
||||
bool hasOwnership() const noexcept {
|
||||
return isOwning;
|
||||
}
|
||||
void invalidate() {
|
||||
void invalidate() noexcept {
|
||||
isOwning = false;
|
||||
}
|
||||
|
||||
@ -223,43 +225,61 @@ struct ArgumentsHint<void> : std::false_type { };
|
||||
|
||||
using AbsentArgumentsHint = ArgumentsHint<void>;
|
||||
|
||||
using EmptyArgumentsHint = ArgumentsHint<>;
|
||||
|
||||
template<typename Function>
|
||||
struct GetArgumentsHint;
|
||||
struct UnwrapArguments;
|
||||
|
||||
template<typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(Args...)>
|
||||
struct UnwrapArguments<ReturnType(Args...)>
|
||||
: std::common_type<ArgumentsHint<Args...>> { };
|
||||
|
||||
/// Mutable function pointers
|
||||
template<typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(*)(Args...)>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(*)(Args...)>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
/// Const function pointers
|
||||
template<typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(*const)(Args...)>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(*const)(Args...)>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
/// Mutable class method pointers
|
||||
template<typename ClassType, typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(ClassType::*)(Args...)>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(ClassType::*)(Args...)>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
/// Const class method pointers
|
||||
template<typename ClassType, typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(ClassType::*)(Args...) const>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(ClassType::*)(Args...) const>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
/// Mutable volatile class method pointers
|
||||
template<typename ClassType, typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(ClassType::*)(Args...) volatile>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(ClassType::*)(Args...) volatile>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
/// Const volatile class method pointers
|
||||
template<typename ClassType, typename ReturnType, typename... Args>
|
||||
struct GetArgumentsHint<ReturnType(ClassType::*)(Args...) const volatile>
|
||||
: GetArgumentsHint<ReturnType(Args...)> { };
|
||||
struct UnwrapArguments<ReturnType(ClassType::*)(Args...) const volatile>
|
||||
: UnwrapArguments<ReturnType(Args...)> { };
|
||||
|
||||
template<typename Functional>
|
||||
using unwrap_functional_t = std::conditional_t<
|
||||
std::is_function<Functional>::value,
|
||||
UnwrapArguments<Functional>,
|
||||
UnwrapArguments<decltype(&Functional::operator())>
|
||||
>;
|
||||
|
||||
template<typename T>
|
||||
using unwrap_continuation_t = typename unwrap_functional_t<
|
||||
typename unwrap_functional_t<T>::type::only_argument_type
|
||||
>::type;
|
||||
|
||||
template<typename T>
|
||||
using unwrap_callback_t = AbsentArgumentsHint;
|
||||
|
||||
/*
|
||||
template<typename T,
|
||||
typename ReturnType, typename... Args,
|
||||
typename Qualifier, typename Config,
|
||||
@ -278,8 +298,10 @@ template<typename T,
|
||||
typename = always_void_t<>>
|
||||
struct InferArgumentsFromType : AbsentArgumentsHint { };
|
||||
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
using InferArgumentsFrom = typename InferArgumentsFromType<T>::type;
|
||||
using InferArgumentsFrom = AbsentArgumentsHint; // typename InferArgumentsFromType<T>::type;
|
||||
|
||||
/*
|
||||
template<typename Function>
|
||||
@ -327,7 +349,7 @@ struct CallbackResultDecorator<void> {
|
||||
static auto decorate(Callback&& callback) {
|
||||
return [callback = std::forward<Callback>(callback)](auto&&... args) {
|
||||
callback(std::forward<decltype(args)>(args)...);
|
||||
return emptyContinuation;
|
||||
return emptyContinuation();
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -382,11 +404,11 @@ auto appendCallback(Continuation&& continuation,
|
||||
}
|
||||
|
||||
template<typename Data>
|
||||
void invokeContinuation(Data data) {
|
||||
void invokeUndecorated(Data data) {
|
||||
// Check whether the ownership is acquired and start the continuation call
|
||||
if (data.ownership.hasOwnership()) {
|
||||
// Pass an empty callback to the continuation to invoke it
|
||||
std::move(data.continuation)(emptyCallback);
|
||||
std::move(data.continuation)(emptyCallback());
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,15 +478,15 @@ public:
|
||||
: data(std::move(data_)) { }
|
||||
|
||||
/// Return a r-value reference to the data
|
||||
template<typename Target>
|
||||
template<typename Hint>
|
||||
auto undecorate()&& {
|
||||
return Undecorator::template undecorate<Target>(std::move(data));
|
||||
return Undecorator::template undecorate<Hint>(std::move(data));
|
||||
}
|
||||
|
||||
/// Return a copy of the data
|
||||
template<typename Target>
|
||||
template<typename Hint>
|
||||
auto undecorate() const& {
|
||||
return Undecorator::template undecorate<Target>(data);
|
||||
return Undecorator::template undecorate<Hint>(data);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -495,24 +517,26 @@ public:
|
||||
|
||||
template<typename Callback>
|
||||
static void requiresUndecorateable() {
|
||||
static_assert(is_undecorateable<Callback>::value,
|
||||
/*static_assert(is_undecorateable<Callback>::value,
|
||||
"Can't retrieve the signature of the given callback. "
|
||||
"Consider to pass an untemplated function or functor "
|
||||
"to the `then` method invocation to fix this.");
|
||||
"to the `then` method invocation to fix this.");*/
|
||||
}
|
||||
|
||||
/// Return a r-value reference to the data
|
||||
template<typename Callback>
|
||||
template<typename... Args>
|
||||
void undecorate()&& {
|
||||
requiresUndecorateable<Callback>();
|
||||
return undecorateCombined<Callback>(std::move(combined));
|
||||
/// TODO
|
||||
// requiresUndecorateable<>();
|
||||
// return undecorateCombined<Callback>(std::move(combined));
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
template<typename... Args>
|
||||
/// Return a copy of the data
|
||||
void undecorate() const& {
|
||||
requiresUndecorateable<Callback>();
|
||||
return undecorateCombined<Callback>(combined);
|
||||
/// TODO
|
||||
// requiresUndecorateable<Callback>();
|
||||
// return undecorateCombined<Callback>(combined);
|
||||
}
|
||||
|
||||
template<typename RightLazyCombine>
|
||||
@ -540,6 +564,11 @@ auto make_continuable(Continuation&& continuation,
|
||||
}));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
auto add_type_hint(T&& continuable) {
|
||||
return std::forward<T>(continuable);
|
||||
}
|
||||
|
||||
template<typename Undecorated, typename Callback>
|
||||
auto thenImpl(Undecorated undecorated, Callback&& callback) {
|
||||
auto next = appendCallback(std::move(undecorated.continuation),
|
||||
@ -596,20 +625,23 @@ public:
|
||||
|
||||
~ContinuableBase() {
|
||||
// Undecorate/materialize the decoration
|
||||
// invokeContinuation(std::move(decoration).template undecorate<void>());
|
||||
invokeUndecorated(std::move(decoration)
|
||||
.template undecorate<EmptyArgumentsHint>());
|
||||
}
|
||||
ContinuableBase(ContinuableBase&&) = default;
|
||||
ContinuableBase(ContinuableBase const&) = default;
|
||||
|
||||
template<typename Callback>
|
||||
auto then(Callback&& callback)&& {
|
||||
return thenImpl(std::move(decoration).template undecorate<Callback>(),
|
||||
using Hint = unwrap_callback_t<Callback>;
|
||||
return thenImpl(std::move(decoration).template undecorate<Hint>(),
|
||||
std::forward<Callback>(callback));
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
auto then(Callback&& callback) const& {
|
||||
return thenImpl(decoration.template undecorate<Callback>(),
|
||||
using Hint = unwrap_callback_t<Callback>;
|
||||
return thenImpl(decoration.template undecorate<Hint>(),
|
||||
std::forward<Callback>(callback));
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "continuable/continuable.hpp"
|
||||
|
||||
|
||||
template<typename... Args>
|
||||
using continuable = decltype(make_continuable(std::declval<std::function<void(Args...)>>));
|
||||
|
||||
@ -12,7 +13,56 @@ static auto makeTestContinuation() {
|
||||
});
|
||||
}
|
||||
|
||||
static auto dnsResolve(std::string) {
|
||||
return make_continuable([](auto&& callback) {
|
||||
callback("");
|
||||
});
|
||||
}
|
||||
|
||||
static auto httpRequestToIp(std::string) {
|
||||
return make_continuable([](auto&& callback) {
|
||||
callback("");
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static auto flatten(T&& factory) {
|
||||
return [factory = std::forward<T>(factory)](auto&&... args) {
|
||||
return factory(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
}
|
||||
|
||||
/*static auto httpRequest(std::string url) {
|
||||
return dnsResolve(url)
|
||||
.then(flatten(httpRequestToIp))
|
||||
.then([](std::string result) {
|
||||
|
||||
});
|
||||
}*/
|
||||
|
||||
struct Debugable {
|
||||
int i = 5;
|
||||
|
||||
template<typename C>
|
||||
void operator() (C&& c) {
|
||||
std::forward<C>(c)(true);
|
||||
}
|
||||
};
|
||||
|
||||
static auto moveTo() {
|
||||
/*return make_continuable([](auto&& callback) {
|
||||
callback(true);
|
||||
});*/
|
||||
|
||||
return make_continuable(Debugable{});
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
|
||||
Debugable deb;
|
||||
|
||||
// moveTo().then([](bool) {});
|
||||
|
||||
// continuable<int, int> c;
|
||||
|
||||
auto dispatcher = SelfDispatcher{};
|
||||
@ -47,14 +97,11 @@ int main(int, char**) {
|
||||
res += val;
|
||||
})
|
||||
.then([] {
|
||||
|
||||
|
||||
|
||||
return makeTestContinuation();
|
||||
})
|
||||
.then(makeTestContinuation())
|
||||
.then([] (std::string arg) {
|
||||
|
||||
arg.clear();
|
||||
});
|
||||
|
||||
return res;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
add_executable(continuable-tests
|
||||
${CMAKE_CURRENT_LIST_DIR}/test-chaining.cpp)
|
||||
${CMAKE_CURRENT_LIST_DIR}/test-chaining.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/test-unwrap.cpp)
|
||||
|
||||
target_link_libraries(continuable-tests
|
||||
PRIVATE
|
||||
|
||||
107
test/test-unwrap.cpp
Normal file
107
test/test-unwrap.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright 2016 Denis Blank <denis.blank@outlook.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "continuable/continuable.hpp"
|
||||
|
||||
/// Contains helper classes to retrieve the arguments a callback
|
||||
/// is called with when passing it to the given function.
|
||||
namespace unwrap {
|
||||
|
||||
} // namespace unwrap
|
||||
|
||||
|
||||
/*template<typename Expression, typename = void_t<>>
|
||||
struct is_compiling
|
||||
: std::false_type { };
|
||||
|
||||
template<typename Expression>
|
||||
struct is_compiling<Expression, void_t<
|
||||
decltype(std::declval<Expression>()(0))>
|
||||
> : std::true_type { };*/
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
struct CanUnwrap
|
||||
|
||||
template<typename T>
|
||||
using CanUnwrapT =
|
||||
*/
|
||||
|
||||
template<typename Functional, typename... Args>
|
||||
using is_argument_hint = Identity<
|
||||
typename unwrap_continuation_t<Functional>::argument_type,
|
||||
Identity<Args...>
|
||||
>;
|
||||
|
||||
#define EXPECT_ARGUMENTS(FUNCTIONAL, ...) \
|
||||
\
|
||||
auto functional = FUNCTIONAL; \
|
||||
using id = Identity<__VA_ARGS__>; \
|
||||
id iiii{}; \
|
||||
Identity<is_argument_hint<decltype(functional), __VA_ARGS__ >> argst; /*\
|
||||
auto result = is_argument_hint< \
|
||||
decltype(functional), __VA_ARGS__ \
|
||||
>::value; \
|
||||
EXPECT_TRUE(result); \*/
|
||||
|
||||
|
||||
TEST(ContinuableUnwrapTests, FunctionsAreUnwrappable) {
|
||||
|
||||
auto fn = [](std::function<void(int, int)>) {
|
||||
|
||||
};
|
||||
|
||||
using tt = typename unwrap_continuation_t<decltype(fn)>::argument_type;
|
||||
|
||||
using tttt = is_argument_hint<decltype(fn), int, int>;
|
||||
|
||||
// auto t = tttt::value;
|
||||
|
||||
// EXPECT_ARGUMENTS(fn, int, int);
|
||||
|
||||
// tt arg;
|
||||
|
||||
// auto tp = typeid(arg).name();
|
||||
|
||||
/*
|
||||
auto op = &decltype(fn)::operator();
|
||||
|
||||
using opt = decltype(op);
|
||||
|
||||
using unwrp = typename UnwrapArguments<opt>::type::only_argument_type;
|
||||
|
||||
using cu = unwrap_functional_t<decltype(fn)>::type::only_argument_type;
|
||||
|
||||
// using unwrp2 = typename UnwrapArguments<unwrp>::type;
|
||||
|
||||
auto u = unwrp{};
|
||||
|
||||
;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// auto t = unwrap_functional<decltype(fn)>;
|
||||
*/
|
||||
|
||||
/*EXPECT_ARGUMENTS();*/
|
||||
|
||||
int i = 0;
|
||||
(void)i;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user