#include <tuple>
#include <iostream>

namespace details
{
    template<typename Int, typename, Int Begin, bool Increasing>
    struct integer_range_impl;

    template<typename Int, Int... N, Int Begin>
    struct integer_range_impl<Int, std::integer_sequence<Int, N...>, Begin, true> {
        using type = std::integer_sequence<Int, N+Begin...>;
    };

    template<typename Int, Int... N, Int Begin>
    struct integer_range_impl<Int, std::integer_sequence<Int, N...>, Begin, false> {
        using type = std::integer_sequence<Int, Begin-N...>;
    };
}

template<typename Int, Int Begin, Int End>
using integer_range = typename details::integer_range_impl<
    Int,
    std::make_integer_sequence<Int, (Begin<End) ? End-Begin : Begin-End>,
    Begin,
    (Begin<End) >::type;

template<std::size_t Begin, std::size_t End>
using index_range = integer_range<std::size_t, Begin, End>;

template<size_t SN, size_t DN, class TSrc, class TDest, class Func>
void tuple_call_assign(TSrc&& source, TDest& target, Func f)
{
    std::get<DN>(target) = f(std::get<SN>(std::forward<TSrc>(source)));	
}

template<size_t From, size_t To, class TSrc, class TDest, class Func, size_t...Is, size_t...DIs>
void tuple_transform(TSrc&& source, TDest& target, Func f,
                     std::index_sequence<Is...>, std::index_sequence<DIs...>)
{
    using expander = int[];
    (void)expander { 0, (tuple_call_assign<Is,DIs>(std::forward<TSrc>(source),target,f), 0)... };
}

template<size_t From, size_t To, size_t FromDest, class TSrc, class TDest, class Func>
void tuple_transform(TSrc&& source, TDest& target, Func f)
{
	static_assert(To > From, "Range must be increasing");
	static_assert(To <= std::tuple_size<std::decay_t<TSrc>>::value+1, 
	     "Range must be valid for source tuple");
	constexpr size_t RangeSize = To-From;
	static_assert(FromDest+RangeSize <= std::tuple_size<std::decay_t<TDest>>::value, 
	     "Range must be valid for target tuple");
	
    tuple_transform<From,To>(std::forward<TSrc>(source), target, f,
                    index_range<From,To>(), index_range<FromDest, FromDest+RangeSize>());
}


int main()
{
	std::tuple<int,int,int> a = std::make_tuple(1,2,3);
	std::tuple<int,int,int> b;
	tuple_transform<0,2,1>(a,b,[](int a){return a*2;});
	std::cout << std::get<0>(b);
	std::cout << std::get<1>(b);
	std::cout << std::get<2>(b);
}