fork download
  1. #include <iostream>
  2. #include <tuple>
  3.  
  4. namespace
  5. {
  6. template<typename T>
  7. using identity = T;
  8.  
  9. template<typename T, typename... V>
  10. struct RAII_Set_impl
  11. {
  12. T &t;
  13. std::tuple<identity<V T::*>...> mop;
  14. std::tuple<V...> ds;
  15. RAII_Set_impl(T &t_, std::tuple<V T::*, V, V>... sets)
  16. : t(t_)
  17. , mop(std::get<0>(sets)...)
  18. , ds(std::get<2>(sets)...)
  19. {
  20. set(std::get<1>(sets)...);
  21. }
  22. ~RAII_Set_impl()
  23. {
  24. unset(typename gens<sizeof...(V)>::type());
  25. }
  26. template<typename... U>
  27. void set(U... u)
  28. {
  29. do_set<0, U...>(u...);
  30. }
  31. template<std::size_t i, typename First, typename... Rest>
  32. void do_set(First first, Rest... rest)
  33. {
  34. t.*std::get<i>(mop) = first;
  35. do_set<i+1, Rest...>(rest...);
  36. }
  37. template<std::size_t i, typename Last>
  38. void do_set(Last last)
  39. {
  40. t.*std::get<i>(mop) = last;
  41. }
  42. template<std::size_t i>
  43. void do_set()
  44. {
  45. }
  46. template<std::size_t...> struct seq{};
  47. template<std::size_t N, std::size_t... S>
  48. struct gens : gens<N-1, N-1, S...> {};
  49. template<std::size_t... S>
  50. struct gens<0, S...>
  51. {
  52. using type = seq<S...>;
  53. };
  54. template<std::size_t... S>
  55. void unset(seq<S...>)
  56. {
  57. set(std::get<S>(ds)...);
  58. }
  59. };
  60. template<typename T, typename... V>
  61. auto RAII_Set(T &t, std::tuple<V T::*, V, V>... sets)
  62. -> RAII_Set_impl<T, V...>
  63. {
  64. return RAII_Set_impl<T, V...>(t, sets...);
  65. }
  66. }
  67.  
  68. struct Test
  69. {
  70. int x, y;
  71. double z;
  72. ~Test()
  73. {
  74. std::cout << "x = " << x << std::endl
  75. << "y = " << y << std::endl
  76. << "z = " << z << std::endl;
  77. }
  78. } t;
  79.  
  80. int main()
  81. {
  82. auto raii_set_t = RAII_Set(t,
  83. std::make_tuple(&Test::x, 1, 2),
  84. std::make_tuple(&Test::y, 3, 4),
  85. std::make_tuple(&Test::z, 5.5, 6.6)
  86. );
  87. std::cout << "x = " << t.x << std::endl
  88. << "y = " << t.y << std::endl
  89. << "z = " << t.z << std::endl;
  90. std::cout << std::endl;
  91. }
  92.  
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
x = 1
y = 3
z = 5.5

x = 2
y = 4
z = 6.6