/** * Copyright 2015-2016 Denis Blank * * 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 #include #include namespace detail { template struct Identity { }; template struct IdentityInheritenceWrapper : Identity, IdentityInheritenceWrapper { }; enum class NamedParameterId { NAMED_PARAMATER_CALLBACK, NAMED_PARAMATER_REJECTOR }; template struct NamedParameter : std::integral_constant, std::common_type { }; template using GetNamedParameterOrDefault = void; template class ContinuableBase; template struct ReturnTypeToContinuableConverter; template struct template class ContinuableBase, CallbackType> { CallbackType callback_; public: explicit ContinuableBase(CallbackType&& callback) : callback_(std::move(callback)) { } void via() { } template auto then(C&& continuation) { // The type the callback will evaluate to using EvaluatedTo = decltype(std::declval()(std::declval()...)); return EvaluatedTo{ }; } }; } // namespace detail using namespace detail; // template // using Continuable = detail::ContinuableBase>; template struct Callback { void operator() (Args... ) { } }; template auto make_continuable(Args&&...) { return Continuable<> { }; } auto http_request(std::string url) { return make_continuable([url](auto& callback) { callback("
hi
"); }); } template auto appendHandlerToContinuation(Continuation&& cont, Handler&& handler) { return [cont = std::forward(cont), handler = std::forward(handler)](auto&& continuation) { using T = decltype(continuation); return [continuation = std::forward(continuation)](auto&&... arg) { continuation(std::forward(arg)...); }; current([continuation = std::forward(continuation)](auto&&... arg) { continuation(std::forward(arg)...); }); }; } */ #include #include #include auto createEmptyContinuation() { return [](auto&& callback) { callback(); }; } auto createEmptyCallback() { return [](auto&&...) { }; } template struct CallbackResultDecorator { template static auto decorate(Callback&& callback) { return std::forward(callback); } }; template<> struct CallbackResultDecorator { template static auto decorate(Callback&& callback) { return [callback = std::forward(callback)](auto&&... args) { callback(std::forward(args)...); return createEmptyContinuation(); }; } }; template auto applyTuple(std::integer_sequence, T&& tuple, F&& function) { return std::forward(function)(std::get(std::forward(tuple))...); } template struct CallbackResultDecorator> { template static auto decorate(Callback&& callback) { return [callback = std::forward(callback)](auto&&... args) { // Receive the tuple from the callback auto result = callback(std::forward(args)...); return [result = std::move(result)] (auto&& callback) mutable { // Generate a sequence for tag dispatching auto constexpr const sequence = std::make_integer_sequence{}; applyTuple(sequence, std::move(result), std::forward(callback)); }; }; } }; // Create the proxy callback that is responsible for invoking // the real callback and passing the next continuation into // to the result of the callback. template auto createProxyCallback(Callback&& callback, Next&& next) { return [callback = std::forward(callback), next = std::forward(next)] (auto&&... args) mutable { using Result = decltype(callback(std::forward(args)...)); using Decorator = CallbackResultDecorator; Decorator::decorate(std::move(callback)) (std::forward(args)...)(std::move(next)); }; } template auto appendHandlerToContinuation(Continuation&& continuation, Callback&& callback) { return [continuation = std::forward(continuation), callback = std::forward(callback)](auto&& next) mutable { // Invoke the next invocation handler std::move(continuation)(createProxyCallback( std::move(callback), std::forward(next))); }; } template void invokeContinuation(Continuation&& continuation) { // Pass an empty callback to the continuation to invoke it std::forward(continuation)(createEmptyCallback()); } auto makeTestContinuation() { return [](auto&& callback) { callback("
hi
"); }; } int main(int, char**) { auto continuation = makeTestContinuation(); auto then1 = [](std::string) { int i = 0; return std::make_tuple(47, 46, 45); }; auto then2 = [](int val1, int val2, int val3) { int i = 0; }; auto f1 = appendHandlerToContinuation(continuation, then1); auto f2 = appendHandlerToContinuation(f1, then2); invokeContinuation(f2); }