fork(18) download
  1. #include <array>
  2. #include <cstddef>
  3. #include <tuple>
  4. #include <type_traits>
  5. #include <iostream>
  6.  
  7. // implementation
  8.  
  9. namespace detail
  10. {
  11. template<std::size_t I>
  12. struct visit_impl
  13. {
  14. template<typename Tuple, typename F, typename ...Args>
  15. inline static constexpr int visit(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(fun(std::get<I - 1U>(tuple), std::forward<Args>(args)...)) && noexcept(visit_impl<I - 1U>::visit(tuple, idx, fun, std::forward<Args>(args)...)))
  16. {
  17. return (idx == (I - 1U) ? (fun(std::get<I - 1U>(tuple), std::forward<Args>(args)...), void(), 0) : visit_impl<I - 1U>::visit(tuple, idx, fun, std::forward<Args>(args)...));
  18. }
  19.  
  20. template<typename R, typename Tuple, typename F, typename ...Args>
  21. inline static constexpr R visit(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(fun(std::get<I - 1U>(tuple), std::forward<Args>(args)...)) && noexcept(visit_impl<I - 1U>::template visit<R>(tuple, idx, fun, std::forward<Args>(args)...)))
  22. {
  23. return (idx == (I - 1U) ? fun(std::get<I - 1U>(tuple), std::forward<Args>(args)...) : visit_impl<I - 1U>::template visit<R>(tuple, idx, fun, std::forward<Args>(args)...));
  24. }
  25. };
  26.  
  27. template<>
  28. struct visit_impl<0U>
  29. {
  30. // template parameter 'I' reached 0U, which means the runtime index did not exist in the tuple (we could throw an exception, but we'll ignore it here)
  31. template<typename Tuple, typename F, typename ...Args>
  32. inline static constexpr int visit(Tuple const&, std::size_t, F, Args&&...) noexcept
  33. {
  34. return 0;
  35. }
  36.  
  37. template<typename R, typename Tuple, typename F, typename ...Args>
  38. inline static constexpr R visit(Tuple const&, std::size_t, F, Args&&...) noexcept(noexcept(R{}))
  39. {
  40. static_assert(std::is_default_constructible<R>::value, "Explicit return type of visit_at method must be default-constructible");
  41. return R{};
  42. }
  43. };
  44. }
  45.  
  46. template<typename Tuple, typename F, typename ...Args>
  47. inline constexpr void visit_at(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(detail::visit_impl<std::tuple_size<Tuple>::value>::visit(tuple, idx, fun, std::forward<Args>(args)...)))
  48. {
  49. detail::visit_impl<std::tuple_size<Tuple>::value>::visit(tuple, idx, fun, std::forward<Args>(args)...);
  50. }
  51.  
  52. template<typename R, typename Tuple, typename F, typename ...Args>
  53. inline constexpr R visit_at(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(detail::visit_impl<std::tuple_size<Tuple>::value>::template visit<R>(tuple, idx, fun, std::forward<Args>(args)...)))
  54. {
  55. return detail::visit_impl<std::tuple_size<Tuple>::value>::template visit<R>(tuple, idx, fun, std::forward<Args>(args)...);
  56. }
  57.  
  58. // demo code
  59.  
  60. int main(int, char**) noexcept
  61. {
  62. static constexpr auto const visitor = [](auto &&v) // standard visitor
  63. {
  64. std::cout << v << std::endl;
  65. };
  66. static constexpr auto const visitor_with_result = [](auto &&v, int inc = 1) -> int // visitor that returns a result (optionally with second parameter)
  67. {
  68. return v + inc;
  69. };
  70. static constexpr auto const tup = std::make_tuple(1, 2, 3, 4, 5);
  71. static constexpr std::array<int, 5U> const arr{ 6, 7, 8, 9, 10 };
  72. for (int i = 0; i < 5; ++i)
  73. {
  74. visit_at(tup, i, visitor); // call standard visitor on tuple
  75. }
  76. std::cout << std::endl;
  77. for (int i = 0; i < 5; ++i)
  78. {
  79. std::cout << visit_at<int>(tup, i, visitor_with_result) << std::endl; // call visitor with result using default second parameter
  80. }
  81. std::cout << std::endl;
  82. for (int i = 0; i < 5; ++i)
  83. {
  84. std::cout << visit_at<int>(arr, i, visitor_with_result, 10) << std::endl; // call visitor with result using explicit second parameter and array instead of tuple
  85. }
  86. return 0;
  87. }
  88.  
Success #stdin #stdout 0s 4360KB
stdin
Standard input is empty
stdout
1
2
3
4
5

2
3
4
5
6

16
17
18
19
20