#include <iostream>
#include <tuple>

namespace
{
	template<typename T>
	using identity = T;

	template<typename T, typename... V>
	struct RAII_Set_impl
	{
		T &t;
		std::tuple<identity<V T::*>...> mop;
		std::tuple<V...> ds;
		RAII_Set_impl(T &t_, std::tuple<V T::*, V, V>... sets)
		: t(t_)
		, mop(std::get<0>(sets)...)
		, ds(std::get<2>(sets)...)
		{
			set(std::get<1>(sets)...);
		}
		~RAII_Set_impl()
		{
			unset(typename gens<sizeof...(V)>::type());
		}
		template<typename... U>
		void set(U... u)
		{
			do_set<0, U...>(u...);
		}
		template<std::size_t i, typename First, typename... Rest>
		void do_set(First first, Rest... rest)
		{
			t.*std::get<i>(mop) = first;
			do_set<i+1, Rest...>(rest...);
		}
		template<std::size_t i, typename Last>
		void do_set(Last last)
		{
			t.*std::get<i>(mop) = last;
		}
		template<std::size_t i>
		void do_set()
		{
		}
		template<std::size_t...> struct seq{};
		template<std::size_t N, std::size_t... S>
		struct gens : gens<N-1, N-1, S...> {};
		template<std::size_t... S>
		struct gens<0, S...>
		{
			using type = seq<S...>;
		};
		template<std::size_t... S>
		void unset(seq<S...>)
		{
			set(std::get<S>(ds)...);
		}
	};
	template<typename T, typename... V>
	auto RAII_Set(T &t, std::tuple<V T::*, V, V>... sets)
	-> RAII_Set_impl<T, V...>
	{
		return RAII_Set_impl<T, V...>(t, sets...);
	}
}

struct Test
{
	int x, y;
	double z;
	~Test()
	{
		std::cout << "x = " << x << std::endl
		          << "y = " << y << std::endl
		          << "z = " << z << std::endl;
	}
} t;

int main()
{
	auto raii_set_t = RAII_Set(t,
		std::make_tuple(&Test::x, 1, 2),
		std::make_tuple(&Test::y, 3, 4),
		std::make_tuple(&Test::z, 5.5, 6.6)
	);
	std::cout << "x = " << t.x << std::endl
	          << "y = " << t.y << std::endl
	          << "z = " << t.z << std::endl;
	std::cout << std::endl;
}
