Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[simix] Add comments about the generic simcalls and rename them
[simgrid.git] / include / xbt / functional.hpp
1 /* Copyright (c) 2015-2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef XBT_FUNCTIONAL_HPP
8 #define XBT_FUNCTIONAL_HPP
9
10 #include <cstdlib>
11
12 #include <exception>
13 #include <functional>
14 #include <future>
15 #include <utility>
16
17 #include <xbt/sysdep.h>
18 #include <xbt/utility.hpp>
19
20 namespace simgrid {
21 namespace xbt {
22
23 class args {
24 private:
25   int argc_ = 0;
26   char** argv_ = nullptr;
27 public:
28
29   // Main constructors
30   args() {}
31
32   void assign(int argc, const char*const* argv)
33   {
34     clear();
35     char** new_argv = xbt_new(char*,argc + 1);
36     for (int i = 0; i < argc; i++)
37       new_argv[i] = xbt_strdup(argv[i]);
38     new_argv[argc] = nullptr;
39     this->argc_ = argc;
40     this->argv_ = new_argv;
41   }
42   args(int argc, const char*const* argv)
43   {
44     this->assign(argc, argv);
45   }
46
47   char** to_argv() const
48   {
49     const int argc = argc_;
50     char** argv = xbt_new(char*, argc + 1);
51     for (int i=0; i< argc; i++)
52       argv[i] = xbt_strdup(argv_[i]);
53     argv[argc] = nullptr;
54     return argv;
55   }
56
57   // Free
58   void clear()
59   {
60     for (int i = 0; i < this->argc_; i++)
61       std::free(this->argv_[i]);
62     std::free(this->argv_);
63     this->argc_ = 0;
64     this->argv_ = nullptr;
65   }
66   ~args() { clear(); }
67
68   // Copy
69   args(args const& that)
70   {
71     this->assign(that.argc(), that.argv());
72   }
73   args& operator=(args const& that)
74   {
75     this->assign(that.argc(), that.argv());
76     return *this;
77   }
78
79   // Move:
80   args(args&& that) : argc_(that.argc_), argv_(that.argv_)
81   {
82     that.argc_ = 0;
83     that.argv_ = nullptr;
84   }
85   args& operator=(args&& that)
86   {
87     this->argc_ = that.argc_;
88     this->argv_ = that.argv_;
89     that.argc_ = 0;
90     that.argv_ = nullptr;
91     return *this;
92   }
93
94   int    argc()            const { return argc_; }
95   char** argv()                  { return argv_; }
96   const char*const* argv() const { return argv_; }
97   char* operator[](std::size_t i) { return argv_[i]; }
98 };
99
100 template<class F> inline
101 std::function<void()> wrapMain(F code, std::shared_ptr<simgrid::xbt::args> args)
102 {
103   return [=]() {
104     code(args->argc(), args->argv());
105   };
106 }
107
108 template<class F> inline
109 std::function<void()> wrapMain(F code, simgrid::xbt::args args)
110 {
111   return wrapMain(std::move(code),
112     std::unique_ptr<simgrid::xbt::args>(new simgrid::xbt::args(std::move(args))));
113 }
114
115 template<class F> inline
116 std::function<void()> wrapMain(F code, int argc, const char*const* argv)
117 {
118   return wrapMain(std::move(code), args(argc, argv));
119 }
120
121 namespace bits {
122 template <class F, class Tuple, std::size_t... I>
123 constexpr auto apply(F&& f, Tuple&& t, simgrid::xbt::index_sequence<I...>)
124   -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...))
125 {
126   return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
127 }
128 }
129
130 /** Call a functional object with the values in the given tuple (from C++17)
131  *
132  *  @code{.cpp}
133  *  int foo(int a, bool b);
134  *
135  *  auto args = std::make_tuple(1, false);
136  *  int res = apply(foo, args);
137  *  @encode
138  **/
139 template <class F, class Tuple>
140 constexpr auto apply(F&& f, Tuple&& t)
141   -> decltype(simgrid::xbt::bits::apply(
142     std::forward<F>(f),
143     std::forward<Tuple>(t),
144     simgrid::xbt::make_index_sequence<
145       std::tuple_size<typename std::decay<Tuple>::type>::value
146     >()))
147 {
148   return simgrid::xbt::bits::apply(
149     std::forward<F>(f),
150     std::forward<Tuple>(t),
151     simgrid::xbt::make_index_sequence<
152       std::tuple_size<typename std::decay<Tuple>::type>::value
153     >());
154 }
155
156 }
157 }
158
159 #endif