wrappers/function_wrappers.hh

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