arglist.H 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // (c) Daniel Llorens - 2011
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file arglist.H
  7. /// @brief Manipulate argument list.
  8. #pragma once
  9. #include "ra/macros.H"
  10. #include <tuple>
  11. // @note It's cleaner to have P0, P ... be parameters of the function and not of the class, but that triggers unimplemented features on gcc 4.5--4.6. Also below shuffle_args<>.
  12. template <int i, class T, class Enable=void>
  13. struct nth_arg_impl;
  14. template <int i, class P0, class ... P>
  15. struct nth_arg_impl<i, std::tuple<P0, P ...>, std::enable_if_t<i==0>>
  16. {
  17. static decltype(auto) f(P0 && p0, P && ... p)
  18. {
  19. return std::forward<P0>(p0);
  20. }
  21. };
  22. template <int i, class P0, class ... P>
  23. struct nth_arg_impl<i, std::tuple<P0, P ...>, std::enable_if_t<(i>0)>>
  24. {
  25. static_assert(i<=sizeof...(P), "bad argument index");
  26. using rest = std::tuple<P ...>;
  27. static auto f(P0 && p0, P && ... p) -> decltype(nth_arg_impl<i-1, rest>::f(std::forward<P>(p) ...))
  28. {
  29. return nth_arg_impl<i-1, rest>::f(std::forward<P>(p) ...);
  30. }
  31. };
  32. template <int i, class ... P>
  33. inline auto nth_arg(P && ... p) -> decltype(nth_arg_impl<i, std::tuple<P ...>>::f(std::forward<P>(p) ...))
  34. {
  35. return nth_arg_impl<i, std::tuple<P ...>>::f(std::forward<P>(p) ...);
  36. }
  37. template <class II, class TT>
  38. struct shuffle_args_impl;
  39. template <class ... I, class ... T>
  40. struct shuffle_args_impl<std::tuple<I ...>, std::tuple<T ...>>
  41. {
  42. using II = std::tuple<I ...>;
  43. using TT = std::tuple<T ...>;
  44. template <class G>
  45. static auto f(G && g, T && ... t) -> decltype(g(nth_arg<I::value>(std::forward<T>(t) ...) ...))
  46. {
  47. return g(nth_arg<I::value>(std::forward<T>(t) ...) ...);
  48. }
  49. template <class G>
  50. static auto ff(T && ... t) -> decltype(G::f(nth_arg<I::value>(std::forward<T>(t) ...) ...))
  51. {
  52. return G::f(nth_arg<I::value>(std::forward<T>(t) ...) ...);
  53. }
  54. };
  55. // when shuffling doesn't change the types.
  56. template <class II, class G, class ... T>
  57. static auto shuffle_args(G && g, T && ... t)
  58. -> decltype(shuffle_args_impl<II, std::tuple<T ...>>::template f(std::forward<G>(g), std::forward<T>(t) ...))
  59. {
  60. return shuffle_args_impl<II, std::tuple<T ...>>::template f(std::forward<G>(g), std::forward<T>(t) ...);
  61. }
  62. // when shuffling changes the types, cannot use a single g.
  63. template <class II, class G, class ... T>
  64. static auto shuffle_args_types(T && ... t)
  65. -> decltype(shuffle_args_impl<II, std::tuple<T ...>>::template ff<G>(std::forward<T>(t) ...))
  66. {
  67. return shuffle_args_impl<II, std::tuple<T ...>>::template ff<G>(std::forward<T>(t) ...);
  68. }