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