more work on arg hints

This commit is contained in:
Denis Blank 2016-11-06 13:33:43 +01:00
parent b4a622047c
commit 6bd0b49064
5 changed files with 235 additions and 48 deletions

@ -1 +1 @@
Subproject commit ecd530865cefdfa7dea58e84f6aa1b548950363d
Subproject commit 3447fc31b4eea1fbcb86fa0e2f5d9ed9f38776bf

View File

@ -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));
}

View File

@ -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;

View File

@ -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
View 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;
}