Skip to content

Instantly share code, notes, and snippets.

@LB--
Created November 16, 2013 07:28
Show Gist options
  • Save LB--/7497122 to your computer and use it in GitHub Desktop.
Save LB--/7497122 to your computer and use it in GitHub Desktop.
#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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment