From 3182c4d258a1949d2d157e906bbdf802c7d376cf Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Fri, 16 Sep 2016 17:43:17 +0200 Subject: [PATCH] more --- NextGen.cpp | 176 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 143 insertions(+), 33 deletions(-) diff --git a/NextGen.cpp b/NextGen.cpp index a7912e8..011790d 100644 --- a/NextGen.cpp +++ b/NextGen.cpp @@ -115,6 +115,16 @@ auto appendHandlerToContinuation(Continuation&& cont, Handler&& handler) { #include #include #include +#include "Continuable.h" + +// Equivalent to C++17's std::void_t which is targets a bug in GCC, +// that prevents correct SFINAE behavior. +// See http://stackoverflow.com/questions/35753920 for details. +template +struct deduce_to_void : std::common_type { }; + +template +using always_void_t = typename deduce_to_void::type; struct SelfDispatcher { template @@ -123,6 +133,9 @@ struct SelfDispatcher { } }; +template +struct Identity { }; + template class ContinuableBase; @@ -139,6 +152,24 @@ auto applyTuple(std::integer_sequence, T&& tuple, F&& function) { return std::forward(function)(std::get(std::forward(tuple))...); } +template +auto tupleMerge(std::integer_sequence, + std::integer_sequence, + std::tuple&& left, std::tuple&& right) { + return std::make_tuple(std::get(std::move(left))..., + std::get(std::move(right))...); +} + +/// Merges the left and the right tuple together in one. +template +auto tupleMerge(std::tuple&& left, + std::tuple&& right) { + return tupleMerge(std::make_integer_sequence{}, + std::make_integer_sequence{}, + std::move(left), std::move(right)); +} + class Ownership { public: Ownership() { } @@ -166,6 +197,61 @@ private: bool isOwning{ true }; }; +template +struct undecorate_function; + +template +struct undecorate_function { + /// The return type of the function. + typedef ReturnType return_type; + /// The argument types of the function as pack in Identity. + typedef Identity argument_type; +}; + +/// Mutable function pointers +template +struct undecorate_function + : undecorate_function { }; + +/// Const function pointers +template +struct undecorate_function + : undecorate_function { }; + +/// Mutable class method pointers +template +struct undecorate_function + : undecorate_function { }; + +/// Const class method pointers +template +struct undecorate_function + : undecorate_function { }; + +/// Mutable volatile class method pointers +template +struct undecorate_function + : undecorate_function { }; + +/// Const volatile class method pointers +template +struct undecorate_function + : undecorate_function { }; + +template +using do_undecorate = std::conditional_t< + std::is_class::value, + decltype(&Function::operator()), + Function>; + +template> +struct is_undecorateable : std::false_type { }; + +template +struct is_undecorateable::return_type +>> : std::true_type { }; + /// Decorates single values template struct CallbackResultDecorator { @@ -322,42 +408,61 @@ private: Data data; }; +template +auto undecorateCombined(Identity, + std::tuple combined) { + +} + +template +auto undecorateCombined(std::tuple combined) { + // using TargetArgs = typename do_undecorate::argument_type; + // return undecorateCombined(TargetArgs{}, std::move(combined)); +} + template class LazyCombineDecoration { public: // TODO - explicit LazyCombineDecoration(Ownership ownership_, Combined combined_) - : ownership(std::move(ownership_)), combined(std::move(combined_)) { } + explicit LazyCombineDecoration(Combined combined_) + : combined(std::move(combined_)) { } // using Config = typename Data::Config; + template + static void requiresUndecorateable() { + static_assert(is_undecorateable::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."); + } + /// Return a r-value reference to the data template void undecorate()&& { + requiresUndecorateable(); + return undecorateCombined(std::move(combined)); } + template /// Return a copy of the data void undecorate() const& { + requiresUndecorateable(); + return undecorateCombined(combined); } template - auto merge(RightLazyCombine&& right) { - + auto merge(RightLazyCombine right) && { + auto merged = tupleMerge(std::move(combined), std::move(right.combined)); + return ContinuableBase> { + LazyCombineDecoration{std::move(merged)} + }; } private: - Ownership ownership; Combined combined; }; -template -struct is_lazy_combined - : std::false_type { }; - -template -struct is_lazy_combined> - : std::true_type { }; - template auto make_continuable(Continuation&& continuation, Dispatcher&& dispatcher = SelfDispatcher{}) noexcept { @@ -398,25 +503,22 @@ auto postImpl(Data data ,NewDispatcher&& newDispatcher) { })); } -template -auto convertToLazyCombine(std::true_type /*is_lazy_combined*/, - Decoration&& decoration) { - return std::forward(decoration); +template +auto toLazyCombined(LazyCombineDecoration decoration) { + return std::move(decoration); } template -auto convertToLazyCombine(std::false_type /*is_lazy_combined*/, - Decoration&& decoration) { - return LazyCombineDecoration>{}; +auto toLazyCombined(Decoration&& decoration) { + auto data = std::forward(decoration).template undecorate(); + return LazyCombineDecoration>(std::move(data)); } template auto combineImpl(LeftDecoration&& leftDecoration, RightDecoration&& rightDecoration) { - return convertToLazyCombine(is_lazy_combined>{}, - std::forward(leftDecoration)) - .add(convertToLazyCombine(is_lazy_combined>{}, - std::forward(rightDecoration))); + return toLazyCombined(std::forward(leftDecoration)) + .merge(toLazyCombined(std::forward(rightDecoration))); } template @@ -430,7 +532,7 @@ public: ~ContinuableBase() { // Undecorate/materialize the decoration - invokeContinuation(std::move(decoration).template undecorate()); + // invokeContinuation(std::move(decoration).template undecorate()); } ContinuableBase(ContinuableBase&&) = default; ContinuableBase(ContinuableBase const&) = default; @@ -443,7 +545,7 @@ public: template auto then(Callback&& callback) const& { - return thenImpl(decoration.undecorate(), + return thenImpl(decoration.template undecorate(), std::forward(callback)); } @@ -479,11 +581,18 @@ public: return combineImpl(decoration, right.decoration); } + template + auto undecorateFor(Callback&&) { + return decoration.template undecorate(); + } + private: /// The Decoration represents the possible lazy materialized /// data of the continuable. /// The decoration pattern is used to make it possible to allow lazy chaining - /// of operators on Continuables like the and expression `&&`. + /// of operators on Continuables like the and expression `&&`, + /// that requires lazy evaluation and the signature of the callback chained + /// with ContinuableBase::then. Decoration decoration; }; @@ -510,16 +619,17 @@ struct FailIfWrongArgs { int main(int, char**) { auto dispatcher = SelfDispatcher{}; - auto unwrap = [](auto&& callback) { - - callback("47"); - }; + (makeTestContinuation() && makeTestContinuation()) + .undecorateFor([]() + { + + }); /*auto unwrapper = [](auto&&... args) { return std::common_type>{}; };*/ - using T = decltype(unwrap(FailIfWrongArgs<0>{})); + // using T = decltype(unwrap(FailIfWrongArgs<0>{})); // using T = decltype(unwrap(std::declval())); // T t{}; @@ -528,7 +638,7 @@ int main(int, char**) { int res = 0; makeTestContinuation() - .then([](std::string /*str*/) { + .then([](std::string) { return std::make_tuple(47, 46, 45); }) // .post(dispatcher)