#include "Callback.h" #include "WeakCallbackContainer.h" #include "Continuable.h" #include #include #include #include #include #include #include enum SpellCastResult { SPELL_FAILED_SUCCESS = 0, SPELL_FAILED_AFFECTING_COMBAT = 1, SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2, SPELL_FAILED_ALREADY_AT_FULL_MANA = 3, SPELL_FAILED_ALREADY_AT_FULL_POWER = 4, SPELL_FAILED_ALREADY_BEING_TAMED = 5 }; template using Optional = boost::optional; Continuable<> Log(std::string const& message) { return make_continuable([=](Callback<>&& callback) { std::cout << message << std::endl; callback(); }); } // Original method taking an optional callback. void CastSpell(int id, Optional> const& callback = boost::none) { std::cout << "Casting " << id << std::endl; // on success call the callback with SPELL_FAILED_SUCCESS if (callback) (*callback)(SPELL_FAILED_SUCCESS); } // Promise wrapped callback decorator. Continuable CastSpellPromise(int id) { return make_continuable([=](Callback&& callback) { CastSpell(id, callback); }); } // Void instant returning continuable promise for testing purposes Continuable<> TrivialPromise(std::string const& msg = "") { return Log(msg).then(make_continuable([=](Callback<>&& callback) { callback(); })); } Continuable Validate() { return make_continuable([=](Callback&& callback) { std::cout << "Validate " << std::endl; callback(true); }); } Continuable&&> MoveTest() { return make_continuable([=](Callback&&>&& callback) { // Move the unique ptr out to test moveability std::unique_ptr ptr(new int(5)); callback(std::move(ptr)); }); } typedef std::unique_ptr Moveable; void testMoveAbleNormal(std::function&&)> callback) { std::unique_ptr ptr(new int(5)); callback(std::move(ptr)); } template void test_unwrap(std::string const& msg) { std::cout << msg << " is unwrappable: " << (fu::is_unwrappable::value ? "true" : "false") << std::endl; } /* template struct Apply { template static inline auto apply(F && f, T && t, A &&... a) -> decltype(Apply::apply( ::std::forward(f), ::std::forward(t), ::std::get(::std::forward(t)), ::std::forward(a)... )) { return Apply::apply(::std::forward(f), ::std::forward(t), ::std::get(::std::forward(t)), ::std::forward(a)... ); } }; template<> struct Apply<0> { template static inline auto apply(F && f, T &&, A &&... a) -> decltype(::std::forward(f)(::std::forward(a)...)) { return ::std::forward(f)(::std::forward(a)...); } }; template inline auto apply(F && f, T && t) -> decltype(Apply< ::std::tuple_size< typename ::std::decay::type >::value>::apply(::std::forward(f), ::std::forward(t))) { return Apply< ::std::tuple_size< typename ::std::decay::type >::value>::apply(::std::forward(f), ::std::forward(t)); } */ int main(int /*argc*/, char** /*argv*/) { CastSpellPromise(1) .then([](SpellCastResult) { return CastSpellPromise(2); }) .then([](SpellCastResult) { std::cout << "Pause a callback (void test) " << std::endl; }) .then(Validate()) .then(TrivialPromise("huhu")) .then(CastSpellPromise(3)) .then(CastSpellPromise(4)) .then(CastSpellPromise(5)) .then([](SpellCastResult) { return Validate(); }); MoveTest() .then([](std::unique_ptr&& ptr) { static_assert(std::is_rvalue_reference::value, "no rvalue"); // Error here std::unique_ptr other = std::move(ptr); }); // Mockup of aggregate methods make_continuable() .all( [] { return TrivialPromise(); }, [] { return TrivialPromise(); }, [] { return TrivialPromise(); } ) .some(2, // Only 2 of 3 must complete [] { return TrivialPromise(); }, [] { return TrivialPromise(); }, [] { return TrivialPromise(); } ) .any( // Any of 2. [] { return TrivialPromise(); }, [] { return TrivialPromise(); } ) .then([] { std::cout << "Finished" << std::endl; }); //Continuable cb = make_continuable([](Callback&& callback) //{ // callback(true); //}); //test_unwrap("void()"); //test_unwrap>("std::function"); //test_unwrap>("std::vector"); //make_continuable([=](Callback<>&&) //{ //}); //int i = 0; //++i; //auto lam = [=](Callback&&) //{ // // on success call the callback with SPELL_FAILED_SUCCESS // // callback(SPELL_FAILED_SUCCESS); //}; //fu::function_type_of_t fun1; //fun1 = lam; //fun1(Callback()); //fu::function_type_of_t> fun2; // //shared_callback_of_t> sc1; //weak_callback_of_t> sc2; // //make_weak_wrapped_callback(sc1); //make_weak_wrapped_callback(sc2); //WeakCallbackContainer callback; // //auto weakCallback = callback([] //{ //}); //typedef Continuable cont123; //typedef Continuable myty1; //typedef Continuable myty2; //// Convertible test // //// Continuable> spell //{ // auto stack = // int iii = 0; // iii = 1; //} //std::vector myvec; //typedef fu::requires_functional_constructible>::type test_assert1; //// typedef fu::requires_functional_constructible>::type test_assert2; //// Brainstorming: this shows an example callback chain //// Given by continuable //std::function&&)> continuable_1 = [](Callback&& callback) //{ // callback(SPELL_FAILED_AFFECTING_COMBAT); //}; //// Implemented by user //std::function&&)>(SpellCastResult)> callback_by_user_1 = [](SpellCastResult) //{ // // Given by continuable // // Fn2 // return [](Callback&& callback) // { // callback(true); // }; //}; //// Implemented by user //std::function&&)>(bool)> cn2 = [](bool val) //{ // // Finished // std::cout << "Callback chain finished! -> " << val << std::endl; // // Given by continuable (auto end) // return [](Callback<>&&) // { // // Empty callback // }; //}; //// Entry point //std::function&&>)> entry = [continuable_1 /*= move*/, callback_by_user_1 /*given by the user (::then(...))*/] // (std::function&&)>) //{ // // Call with auto created wrapper by the continuable // continuable_1([&](SpellCastResult result /*forward args*/) // { // // Wrapper functional to process unary or multiple promised callbacks // // Returned from the user // std::function&&)> fn2 = callback_by_user_1(/*forward args*/ result); // return std::move(fn2); // }); //}; //// Here we go //entry(); detail::unary_chainer_t< std::function()> >::callback_arguments_t args213987; typedef detail::functional_traits<>::result_maker_of_t< std::function()>, decltype(CastSpellPromise(2)), decltype(TrivialPromise()), std::function()>, std::function()> > maker; maker::arguments_t test282_args; maker::partial_results_t test282_pack; auto test282_size = maker::size; // static_assert(std::is_same<>::value, detail::concat_identities, fu::identity>::type myt; // fu::identity::position<1>> i; std::tuple> tup; Moveable moveable(new int(7)); auto myargs = std::make_tuple(7, std::vector({ 1, 2, 3 }), std::move(moveable)); std::function, Moveable&&)> lam = [](int given_i, std::vector given_vec, Moveable&& moveable) { Moveable other = std::move(moveable); ++given_i; return 1; }; fu::invoke_from_tuple(lam, std::move(myargs)); fu::sequence_generator<2>::type seqtype; fu::sequence_generator<1>::type zero_seqtype; detail::multiple_when_all_chainer_t< fu::identity<>, fu::identity< std::function()>, std::function()> > >::result_maker::partial_results_t myres123345; auto firstType = detail::multiple_when_all_chainer_t< fu::identity<>, fu::identity< std::function()>, std::function()>, std::function()> > >::make_when_all( [] { return make_continuable(); }, [] { return CastSpellPromise(10); }, [] { return CastSpellPromise(20); }) .then([](SpellCastResult, SpellCastResult) { }); std::cout << "ok" << std::endl; return 0; }