fork download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <string>
  4. using namespace std;
  5.  
  6. struct A {};
  7. struct B {};
  8. struct C {};
  9. struct D {};
  10. struct E {};
  11.  
  12. template <typename H>
  13. auto foo (H h, enable_if_t<
  14. is_same<typename result_of<H(A)>::type, bool>::value>* = 0)
  15. {
  16. return [h] (B x) { return h (A {}); };
  17. }
  18.  
  19. template <typename H>
  20. auto foo (H h, enable_if_t<
  21. is_same<typename result_of<H(B)>::type, bool>::value>* = 0)
  22. {
  23. return [h] (C x) { return h (B {}); };
  24. }
  25.  
  26. template <typename H>
  27. auto foo (H h, enable_if_t<
  28. is_same<typename result_of<H(C)>::type, bool>::value>* = 0)
  29. {
  30. return [h] (D x) { return h (C {}); };
  31. }
  32.  
  33. template <typename H>
  34. auto foo (H h, enable_if_t<
  35. is_same<typename result_of<H(D)>::type, bool>::value>* = 0)
  36. {
  37. return [h] (E x) { return h (D {}); };
  38. }
  39.  
  40. struct fooify {
  41. template<class...Args>
  42. auto operator()(Args&&...args)const{
  43. return foo(std::forward<Args>(args)...);
  44. }
  45. };
  46.  
  47. template<class Action, template<class...>class test, class Arg, class=void>
  48. struct repeat_until_helper {
  49. using action_result = result_of_t< Action&(Arg) >;
  50. auto operator()(Action&& action, Arg&&arg)const {
  51. return repeat_until_helper<Action, test, action_result>{}(
  52. std::forward<Action>(action),
  53. action( std::forward<Arg>(arg) )
  54. );
  55. }
  56. };
  57. template<class Action, template<class...>class test, class Arg>
  58. struct repeat_until_helper< Action, test, Arg,
  59. std::enable_if_t< test<Arg>{} >
  60. > {
  61. auto operator()(Action&& action, Arg&&arg)const {
  62. return std::forward<Arg>(arg);
  63. }
  64. };
  65.  
  66. template<class X, class=void>
  67. struct can_be_called_with_E:std::false_type{};
  68. template<class X>
  69. struct can_be_called_with_E<X,
  70. decltype(
  71. void(
  72. std::declval<X>()(std::declval<E>())
  73. )
  74. )
  75. >:std::true_type{};
  76.  
  77. template<template<class...>class test, class Action, class Arg>
  78. auto repeat_until( Action&& action, Arg&& arg) {
  79. return repeat_until_helper< Action, test, Arg >{}( std::forward<Action>(action), std::forward<Arg>(arg) );
  80. }
  81. int main ()
  82. {
  83. auto inner_handler = [] (A) -> bool { return false; };
  84.  
  85. auto f = repeat_until< can_be_called_with_E >( fooify{}, inner_handler );
  86. // auto f = foo (foo (foo (foo ( inner_handler ))));
  87. // auto f = call_until<E> ( inner_handler );
  88.  
  89. std::cout << f (E {}) << "\n";
  90. }
Success #stdin #stdout 0s 3140KB
stdin
Standard input is empty
stdout
0