Guest User

Untitled

a guest
Jan 20th, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.92 KB | None | 0 0
  1. #include <optional>
  2. #include <variant>
  3. #include <utility>
  4. #include <string>
  5. #include <tuple>
  6.  
  7. namespace logic
  8. {
  9. template<typename T>
  10. struct is_optional : std::false_type
  11. {
  12. };
  13.  
  14. template<typename T>
  15. struct is_optional<std::optional<T>> : std::true_type
  16. {
  17. };
  18.  
  19. template<typename T>
  20. static constexpr bool is_optional_v = is_optional<T>::value;
  21.  
  22. struct failure_tag
  23. {
  24. };
  25.  
  26. template<typename Function, typename ArgType>
  27. struct invoke_result
  28. {
  29. private:
  30. using raw_type = std::invoke_result_t<Function, ArgType>;
  31. static_assert(is_optional_v<raw_type>, "only functions returning optional are supported");
  32. public:
  33. using type = typename raw_type::value_type;
  34. };
  35.  
  36. template<typename Function, typename ArgType>
  37. using invoke_result_t = typename invoke_result<Function, ArgType>::type;
  38.  
  39. namespace detail
  40. {
  41. template<typename RetType, typename T, typename Function, typename ... Rest>
  42. RetType get_first_success(const T& value,
  43. Function&& function,
  44. Rest&& ... otherFunctions)
  45. {
  46. auto result = std::forward<Function>(function)(value);
  47.  
  48. if (result.has_value()) {
  49. return result.value();
  50. }
  51.  
  52. if constexpr (sizeof...(Rest) == 0) //return failure tag if reachend end of chain
  53. {
  54. return {};
  55. } else {
  56. return get_first_success<RetType>(value, std::forward<Rest>(otherFunctions)...);
  57. }
  58. }
  59. }
  60.  
  61. template<typename T, typename ... Functions>
  62. std::variant<failure_tag, invoke_result_t<Functions, const T&>...>
  63. sequenced_try(const T& value, Functions&& ... functions)
  64. {
  65. using return_type = std::variant<failure_tag, invoke_result_t<Functions, const T&>...>;
  66. return detail::get_first_success<return_type>(value, std::forward<Functions>(functions)...);
  67. }
  68. }
  69.  
  70. std::optional<std::string> stringify(int x)
  71. {
  72. if (x != 1) {
  73. return {};
  74. }
  75.  
  76. return std::to_string(x);
  77. }
  78.  
  79. std::optional<int> do_nothing(int x)
  80. {
  81. return x;
  82. }
  83.  
  84. std::optional<std::array<int, 2>> duplicate(int x)
  85. {
  86. if (x != 2) {
  87. return {};
  88. }
  89.  
  90. return {{x, x}};
  91. }
  92.  
  93. int main()
  94. {
  95. // is_optional_v tests
  96. static_assert(!logic::is_optional_v<int>);
  97. static_assert(logic::is_optional_v<std::optional<int>>);
  98.  
  99. static_assert(!logic::is_optional_v<decltype("asd")>);
  100. static_assert(logic::is_optional_v<std::optional<decltype("asd")>>);
  101.  
  102. auto result = logic::sequenced_try(1, stringify, do_nothing, duplicate);
  103.  
  104. //sequenced try tests
  105. if (result.index() != 1) {
  106. throw std::logic_error{"sequenced try didn't short-circuit correctly"};
  107. }
  108.  
  109. result = logic::sequenced_try(2, stringify, do_nothing, duplicate);
  110. if (result.index() != 2) {
  111. throw std::logic_error{"sequenced try doesn't work correctly"};
  112. }
  113. }
Add Comment
Please, Sign In to add comment