ref_tuple.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #include <boost/hana/assert.hpp>
  5. #include <boost/hana/at.hpp>
  6. #include <boost/hana/core/make.hpp>
  7. #include <boost/hana/core/tag_of.hpp>
  8. #include <boost/hana/drop_front.hpp>
  9. #include <boost/hana/is_empty.hpp>
  10. #include <boost/hana/not.hpp>
  11. #include <boost/hana/tuple.hpp>
  12. #include <cstddef>
  13. #include <functional>
  14. namespace hana = boost::hana;
  15. // A tuple that holds reference_wrappers to its elements, instead of the
  16. // elements themselves.
  17. struct RefTuple { };
  18. template <typename ...T>
  19. struct ref_tuple;
  20. template <typename ...T>
  21. struct ref_tuple<T&...> {
  22. hana::tuple<std::reference_wrapper<T>...> storage_;
  23. };
  24. namespace boost { namespace hana {
  25. template <typename ...T>
  26. struct tag_of<ref_tuple<T...>> {
  27. using type = RefTuple;
  28. };
  29. template <>
  30. struct make_impl<RefTuple> {
  31. template <typename ...T>
  32. static constexpr auto apply(T& ...t) {
  33. return ref_tuple<T&...>{{std::ref(t)...}};
  34. }
  35. };
  36. template <>
  37. struct at_impl<RefTuple> {
  38. template <typename Xs, typename N>
  39. static constexpr decltype(auto) apply(Xs&& xs, N const& n) {
  40. return hana::at(static_cast<Xs&&>(xs).storage_, n).get();
  41. }
  42. };
  43. template <>
  44. struct is_empty_impl<RefTuple> {
  45. template <typename Xs>
  46. static constexpr auto apply(Xs const& xs) {
  47. return hana::is_empty(xs.storage_);
  48. }
  49. };
  50. template <>
  51. struct drop_front_impl<RefTuple> {
  52. template <std::size_t n, typename T, typename ...U, std::size_t ...i>
  53. static constexpr auto helper(ref_tuple<T, U...> xs, std::index_sequence<i...>) {
  54. return hana::make<RefTuple>(hana::at_c<n + i>(xs.storage_).get()...);
  55. }
  56. template <typename ...T, typename N>
  57. static constexpr auto apply(ref_tuple<T...> xs, N const&) {
  58. return helper<N::value>(xs, std::make_index_sequence<(
  59. N::value < sizeof...(T) ? sizeof...(T) - N::value : 0
  60. )>{});
  61. }
  62. };
  63. }} // end namespace boost::hana
  64. int main() {
  65. int i = 0, j = 1, k = 2;
  66. ref_tuple<int&, int&, int&> refs = hana::make<RefTuple>(i, j, k);
  67. hana::at_c<0>(refs) = 3;
  68. BOOST_HANA_RUNTIME_CHECK(i == 3);
  69. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::is_empty(refs)));
  70. ref_tuple<int&, int&> tail = hana::drop_front(refs);
  71. hana::at_c<0>(tail) = 4;
  72. BOOST_HANA_RUNTIME_CHECK(j == 4);
  73. }