wrappers/function_wrappers.hh

00001 // This file is a part of Catsfoot.
00002 // Copyright (C) 2011  Uni Research
00003 //
00004 // This program is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
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