Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <optional>
- #include <variant>
- #include <utility>
- #include <string>
- #include <tuple>
- namespace logic
- {
- template<typename T>
- struct is_optional : std::false_type
- {
- };
- template<typename T>
- struct is_optional<std::optional<T>> : std::true_type
- {
- };
- template<typename T>
- static constexpr bool is_optional_v = is_optional<T>::value;
- struct failure_tag
- {
- };
- template<typename Function, typename ArgType>
- struct invoke_result
- {
- private:
- using raw_type = std::invoke_result_t<Function, ArgType>;
- static_assert(is_optional_v<raw_type>, "only functions returning optional are supported");
- public:
- using type = typename raw_type::value_type;
- };
- template<typename Function, typename ArgType>
- using invoke_result_t = typename invoke_result<Function, ArgType>::type;
- namespace detail
- {
- template<typename RetType, typename T, typename Function, typename ... Rest>
- RetType get_first_success(const T& value,
- Function&& function,
- Rest&& ... otherFunctions)
- {
- auto result = std::forward<Function>(function)(value);
- if (result.has_value()) {
- return result.value();
- }
- if constexpr (sizeof...(Rest) == 0) //return failure tag if reachend end of chain
- {
- return {};
- } else {
- return get_first_success<RetType>(value, std::forward<Rest>(otherFunctions)...);
- }
- }
- }
- template<typename T, typename ... Functions>
- std::variant<failure_tag, invoke_result_t<Functions, const T&>...>
- sequenced_try(const T& value, Functions&& ... functions)
- {
- using return_type = std::variant<failure_tag, invoke_result_t<Functions, const T&>...>;
- return detail::get_first_success<return_type>(value, std::forward<Functions>(functions)...);
- }
- }
- std::optional<std::string> stringify(int x)
- {
- if (x != 1) {
- return {};
- }
- return std::to_string(x);
- }
- std::optional<int> do_nothing(int x)
- {
- return x;
- }
- std::optional<std::array<int, 2>> duplicate(int x)
- {
- if (x != 2) {
- return {};
- }
- return {{x, x}};
- }
- int main()
- {
- // is_optional_v tests
- static_assert(!logic::is_optional_v<int>);
- static_assert(logic::is_optional_v<std::optional<int>>);
- static_assert(!logic::is_optional_v<decltype("asd")>);
- static_assert(logic::is_optional_v<std::optional<decltype("asd")>>);
- auto result = logic::sequenced_try(1, stringify, do_nothing, duplicate);
- //sequenced try tests
- if (result.index() != 1) {
- throw std::logic_error{"sequenced try didn't short-circuit correctly"};
- }
- result = logic::sequenced_try(2, stringify, do_nothing, duplicate);
- if (result.index() != 2) {
- throw std::logic_error{"sequenced try doesn't work correctly"};
- }
- }
Add Comment
Please, Sign In to add comment