+};
+
+template <class F> inline std::function<void()> wrap_main(F code, std::vector<std::string>&& args)
+{
+ return MainFunction<F>(std::move(code), std::move(args));
+}
+
+template <class F> inline std::function<void()> wrap_main(F code, int argc, const char* const argv[])
+{
+ std::vector<std::string> args(argv, argv + argc);
+ return MainFunction<F>(std::move(code), std::move(args));
+}
+
+namespace bits {
+template <class F, class Tuple, std::size_t... I>
+constexpr auto apply(F&& f, Tuple&& t, std::index_sequence<I...>)
+ -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...))
+{
+ return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
+}
+}
+
+/** Call a functional object with the values in the given tuple (from C++17)
+ *
+ * @code{.cpp}
+ * int foo(int a, bool b);
+ *
+ * auto args = std::make_tuple(1, false);
+ * int res = apply(foo, args);
+ * @endcode
+ **/
+template <class F, class Tuple>
+constexpr auto apply(F&& f, Tuple&& t) -> decltype(
+ simgrid::xbt::bits::apply(std::forward<F>(f), std::forward<Tuple>(t),
+ std::make_index_sequence<std::tuple_size<typename std::decay_t<Tuple>>::value>()))
+{
+ return simgrid::xbt::bits::apply(std::forward<F>(f), std::forward<Tuple>(t),
+ std::make_index_sequence<std::tuple_size<typename std::decay_t<Tuple>>::value>());
+}
+
+template<class T> class Task;
+
+/** Type-erased run-once task
+ *
+ * * Like std::function but callable only once.
+ * However, it works with move-only types.
+ *
+ * * Like std::packaged_task<> but without the shared state.
+ */
+template<class R, class... Args>
+class Task<R(Args...)> {
+ // Placeholder for some class type:
+ struct whatever {};
+
+ // Union used for storage:
+ using TaskUnion =
+ typename std::aligned_union_t<0, void*, std::pair<void (*)(), void*>, std::pair<void (whatever::*)(), whatever*>>;