00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef CALL_WITH_HH
00018 # define CALL_WITH_HH
00019
00020 # include <tuple>
00021 # include "../concept/concepts.hh"
00022
00023 namespace catsfoot {
00024
00025 namespace details {
00026 template <typename T>
00027 struct add_const_ref {
00028 typedef const T& type;
00029 };
00030
00031 template <typename T>
00032 struct add_ref {
00033 typedef T& type;
00034 };
00035
00036 template <typename Op, typename Tuple>
00037 struct call_with_ret {
00038 };
00039
00040 template <typename Op, typename... Args>
00041 struct call_with_ret<Op, std::tuple<Args...>&> {
00042 typedef
00043 decltype(std::declval<Op>()(std::declval<typename add_ref<Args>::type>()...))
00044 type;
00045 static const size_t size = sizeof...(Args);
00046 };
00047
00048 template <typename Op, typename... Args>
00049 struct call_with_ret<Op, std::tuple<Args...> > {
00050 typedef
00051 decltype(std::declval<Op>()(std::declval<typename add_ref<Args>::type>()...))
00052 type;
00053 static const size_t size = sizeof...(Args);
00054 };
00055
00056 template <typename Op, typename... Args>
00057 struct call_with_ret<Op, const std::tuple<Args...>&> {
00058 typedef
00059 decltype(std::declval<Op>()(std::declval<typename add_const_ref<Args>::type>()...))
00060 type;
00061 static const size_t size = sizeof...(Args);
00062 };
00063
00064 template <typename Op, typename Tuple,
00065 typename... Given,
00066 typename = typename std::enable_if<(sizeof...(Given) == call_with_ret<Op, Tuple>::size)>::type>
00067 typename call_with_ret<Op, Tuple>::type
00068 call_with_it(Op&& op, Tuple&&, Given&&... args) {
00069 return std::forward<Op>(op)(std::forward<Given>(args)...);
00070 }
00071
00072 template <typename Op, typename Tuple,
00073 typename... OtherArgs,
00074 typename = typename std::enable_if<(sizeof...(OtherArgs) != call_with_ret<Op, Tuple>::size)>::type,
00075 typename = void>
00076 typename call_with_ret<Op, Tuple>::type
00077 call_with_it(Op&& op, Tuple&& args,
00078 OtherArgs&&... otherargs) {
00079 return call_with_it(std::forward<Op>(op), std::forward<Tuple>(args),
00080 std::forward<OtherArgs>(otherargs)...,
00081 std::get<sizeof...(OtherArgs)>(args));
00082 }
00083 }
00084
00090 template <typename Op, typename Tuple>
00091 typename details::call_with_ret<Op, Tuple>::type
00092 call_with(Op&& op, Tuple&& args) {
00093 return details::call_with_it(std::forward<Op>(op), std::forward<Tuple>(args));
00094 }
00095
00096 }
00097
00098 #endif