00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef FUNCION_WRAPPERS_HH
00018 # define FUNCION_WRAPPERS_HH
00019
00020 # include <functional>
00021 # include <memory>
00022 # include "../utils/call_with.hh"
00023
00024 namespace catsfoot {
00025
00026 namespace details {
00027 template <typename T>
00028 struct member_wrapper;
00029
00031 template <typename T, typename Ret, typename... Args>
00032 struct member_wrapper<Ret (T::*)(Args...)> {
00033 private:
00034 Ret (T::*f)(Args...);
00035
00036 public:
00037 member_wrapper(Ret (T::*f)(Args...)): f(f) {}
00038
00039 Ret operator()(T& t, Args&&... args...) const {
00040 return (t.*f)(std::forward<Args>(args)...);
00041 }
00042 };
00043
00045 template <typename T, typename... Args>
00046 struct member_wrapper<void (T::*)(Args...)> {
00047 private:
00048 void (T::*f)(Args...);
00049
00050 public:
00051 member_wrapper(void (T::*f)(Args...)): f(f) {}
00052
00053 T operator()(T t, Args&&... args...) const {
00054 (t.*f)(std::forward<Args>(args)...);
00055 return t;
00056 }
00057 };
00058
00060 template <typename T, typename Ret, typename... Args>
00061 struct member_wrapper<Ret (T::*)(Args...)const> {
00062 private:
00063 Ret (T::*f)(Args...)const;
00064
00065 public:
00066 member_wrapper(Ret (T::*f)(Args...)const): f(f) {}
00067
00068 Ret operator()(const T& t, Args&&... args...) const {
00069 return (t.*f)(std::forward<Args>(args)...);
00070 }
00071 };
00072
00073 }
00074
00076 template <typename T, typename Ret, typename... Args>
00077 std::function<Ret (T&, Args...)>
00078 wrap(Ret (T::*f)(Args...)) {
00079 return details::member_wrapper<Ret (T::*)(Args...)>(f);
00080 }
00081
00085 template <typename T, typename... Args>
00086 std::function<T (T&, Args...)>
00087 wrap(void (T::*f)(Args...)) {
00088 return details::member_wrapper<void (T::*)(Args...)>(f);
00089 }
00090
00092 template <typename T, typename Ret, typename... Args>
00093 std::function<Ret (const T&, Args...)>
00094 wrap(Ret (T::*f)(Args...) const) {
00095 return details::member_wrapper<Ret (T::*)(Args...)const>(f);
00096 }
00097
00099 template <typename Ret, typename... Args>
00100 std::function<Ret (Args...)>
00101 wrap(Ret (*f)(Args...)) {
00102 return f;
00103 }
00104
00106 template <typename T>
00107 std::function<T> wrap(const std::function<T>& f) {
00108 return f;
00109 }
00110
00112 template <typename T>
00113 std::function<T> wrap(std::function<T>&& f) {
00114 return std::move(f);
00115 }
00116
00119 template <typename T>
00120 struct wrapped {
00121 typedef decltype(wrap(std::declval<T>())) type;
00122 };
00123
00127 template <typename... Args>
00128 struct disamb {
00129 private:
00130 template <typename Ret, typename T>
00131 struct fun {
00132 typedef Ret (T::*type)(Args...);
00133 typedef Ret (*fun_type)(Args...);
00134 };
00135
00136 public:
00137 template <typename Ret, typename T>
00138 typename fun<Ret,T>::type
00139 operator()(Ret (T::*f)(Args...)) const {
00140 return f;
00141 }
00142
00143 template <typename Ret, typename T>
00144 typename fun<Ret,T>::fun_type
00145 operator()(Ret (*f)(Args...)) const {
00146 return f;
00147 }
00148 };
00149
00153 template <typename... Args>
00154 struct disamb_const {
00155 private:
00156 template <typename Ret, typename T>
00157 struct fun {
00158 typedef Ret (T::*const_type)(Args...) const;
00159 };
00160
00161 public:
00162 template <typename Ret, typename T>
00163 typename fun<Ret,T>::const_type
00164 operator()(Ret (T::*f)(Args...) const) const {
00165 return f;
00166 }
00167 };
00168
00170 template <typename T>
00171 struct constructor_wrap {
00172 template <typename... Args>
00173 T operator()(Args&&... args) const {
00174 return T(std::forward<Args>(args)...);
00175 }
00176 };
00177
00178 namespace details {
00179 template <typename T>
00180 struct return_of {};
00181
00182 template <typename T, typename... Args>
00183 struct return_of<T(Args...)> {
00184 typedef T type;
00185 };
00186 }
00187
00190 template <typename T>
00191 std::function<T> constructor() {
00192 return constructor_wrap<typename details::return_of<T>::type>();
00193 }
00194
00195 namespace details {
00196 template <typename T,
00197 typename = typename std::enable_if<!std::is_reference<T>::value>::type>
00198 T copy_if_non_const(T&& t) {
00199 return std::move(t);
00200 }
00201
00202 template <typename T>
00203 T copy_if_non_const(T& t) {
00204 return T(t);
00205 }
00206
00207 template <typename T>
00208 const T& copy_if_non_const(const T& t) {
00209 return t;
00210 }
00211
00212 template <typename T>
00213 struct remove_side_effect_helper {
00214 private:
00215 T function;
00216 public:
00217 template <typename U,
00218 typename = typename
00219 std::enable_if
00220 <std::is_same<typename std::decay<U>::type,
00221 T>::value>
00222 ::type>
00223 remove_side_effect_helper(U&& u): function(std::forward<U>(u)) {}
00224
00225 remove_side_effect_helper(const remove_side_effect_helper& other)
00226 : function(other.function) {}
00227 remove_side_effect_helper(remove_side_effect_helper&& other)
00228 : function(std::move(other.function)) {}
00229
00230 template <typename... Args,
00231 typename Ret =
00232 decltype(std::declval<T>()(std::declval<Args>()...))>
00233 Ret operator()(Args&&... args) const {
00234 std::tuple<decltype(copy_if_non_const(std::forward<Args>(args)))...>
00235 ret =
00236 std::tuple<decltype(copy_if_non_const(std::forward<Args>(args)))...>
00237 (copy_if_non_const(std::forward<Args>(args))...);
00238 return call_with(function, ret);
00239 }
00240 };
00241
00242 }
00243
00244 template <typename T>
00245 details::remove_side_effect_helper<typename std::decay<T>::type>
00246 remove_side_effect(T t) {
00247 return details::remove_side_effect_helper<typename std::decay<T>::type>(t);
00248 }
00249
00250 }
00251
00252 #endif