fork(5) download
  1. #include <tuple>
  2. #include <iostream>
  3.  
  4. namespace details
  5. {
  6. template<typename Int, typename, Int Begin, bool Increasing>
  7. struct integer_range_impl;
  8.  
  9. template<typename Int, Int... N, Int Begin>
  10. struct integer_range_impl<Int, std::integer_sequence<Int, N...>, Begin, true> {
  11. using type = std::integer_sequence<Int, N+Begin...>;
  12. };
  13.  
  14. template<typename Int, Int... N, Int Begin>
  15. struct integer_range_impl<Int, std::integer_sequence<Int, N...>, Begin, false> {
  16. using type = std::integer_sequence<Int, Begin-N...>;
  17. };
  18. }
  19.  
  20. template<typename Int, Int Begin, Int End>
  21. using integer_range = typename details::integer_range_impl<
  22. Int,
  23. std::make_integer_sequence<Int, (Begin<End) ? End-Begin : Begin-End>,
  24. Begin,
  25. (Begin<End) >::type;
  26.  
  27. template<std::size_t Begin, std::size_t End>
  28. using index_range = integer_range<std::size_t, Begin, End>;
  29.  
  30. template<size_t SN, size_t DN, class TSrc, class TDest, class Func>
  31. void tuple_call_assign(TSrc&& source, TDest& target, Func f)
  32. {
  33. std::get<DN>(target) = f(std::get<SN>(std::forward<TSrc>(source)));
  34. }
  35.  
  36. template<size_t From, size_t To, class TSrc, class TDest, class Func, size_t...Is, size_t...DIs>
  37. void tuple_transform(TSrc&& source, TDest& target, Func f,
  38. std::index_sequence<Is...>, std::index_sequence<DIs...>)
  39. {
  40. using expander = int[];
  41. (void)expander { 0, (tuple_call_assign<Is,DIs>(std::forward<TSrc>(source),target,f), 0)... };
  42. }
  43.  
  44. template<size_t From, size_t To, size_t FromDest, class TSrc, class TDest, class Func>
  45. void tuple_transform(TSrc&& source, TDest& target, Func f)
  46. {
  47. static_assert(To > From, "Range must be increasing");
  48. static_assert(To <= std::tuple_size<std::decay_t<TSrc>>::value+1,
  49. "Range must be valid for source tuple");
  50. constexpr size_t RangeSize = To-From;
  51. static_assert(FromDest+RangeSize <= std::tuple_size<std::decay_t<TDest>>::value,
  52. "Range must be valid for target tuple");
  53.  
  54. tuple_transform<From,To>(std::forward<TSrc>(source), target, f,
  55. index_range<From,To>(), index_range<FromDest, FromDest+RangeSize>());
  56. }
  57.  
  58.  
  59. int main()
  60. {
  61. std::tuple<int,int,int> a = std::make_tuple(1,2,3);
  62. std::tuple<int,int,int> b;
  63. tuple_transform<0,2,1>(a,b,[](int a){return a*2;});
  64. std::cout << std::get<0>(b);
  65. std::cout << std::get<1>(b);
  66. std::cout << std::get<2>(b);
  67. }
Success #stdin #stdout 0s 3096KB
stdin
Standard input is empty
stdout
024