Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_COMMON_BIND_HPP
7 : #define IROHA_COMMON_BIND_HPP
8 :
9 : #include <type_traits>
10 : #include <utility>
11 :
12 : namespace iroha {
13 :
14 : /**
15 : * Bind operator. If argument has value, dereferences argument and calls
16 : * given function, which should return wrapped value
17 : * operator| is used since it has to be binary and left-associative
18 : * Non-void returning specialization
19 : *
20 : * boost::optional<int> f();
21 : * boost::optional<double> g(int);
22 : *
23 : * boost::optional<double> d = f()
24 : * | g;
25 : *
26 : * std::forward should be used in any reference of arguments because
27 : * operator bool, operator*, and operator() of arguments can have
28 : * different implementation with ref-qualifiers
29 : *
30 : * Trailing return type checks that result of applying function to
31 : * unwrapped value results in non-void type
32 : *
33 : * @tparam T - monadic type
34 : * @tparam Transform - transform function type
35 : * @param t - monadic value
36 : * @param f - function, which takes dereferenced value, and returns
37 : * wrapped value
38 : * @return monadic value, which can be of another type
39 : */
40 : template <typename T, typename Transform>
41 : auto operator|(T &&t, Transform &&f) -> std::enable_if_t<
42 : not std::is_same<
43 : decltype(std::forward<Transform>(f)(*std::forward<T>(t))),
44 : void>::value,
45 : decltype(std::forward<Transform>(f)(*std::forward<T>(t)))> {
46 7638 : if (std::forward<T>(t)) {
47 7602 : return std::forward<Transform>(f)(*std::forward<T>(t));
48 : }
49 41 : return {};
50 7639 : }
51 :
52 : /**
53 : * Bind operator. If argument has value, dereferences argument and calls
54 : * given function, which should return wrapped value
55 : * operator| is used since it has to be binary and left-associative
56 : * Void specialization
57 : *
58 : * boost::optional<int> f();
59 : * void g(int);
60 : *
61 : * f() | g;
62 : *
63 : * std::forward should be used in any reference of arguments because
64 : * operator bool, operator*, and operator() of arguments can have
65 : * different implementation with ref-qualifiers
66 : *
67 : * Trailing return type checks that result of applying function to
68 : * unwrapped value results in void type
69 : *
70 : * @tparam T - monadic type
71 : * @tparam Transform - transform function type
72 : * @param t - monadic value
73 : * @param f - function, which takes dereferenced value, and returns
74 : * wrapped value
75 : */
76 : template <typename T, typename Transform>
77 : auto operator|(T &&t, Transform &&f) -> std::enable_if_t<
78 : std::is_same<decltype(std::forward<Transform>(f)(*std::forward<T>(t))),
79 : void>::value> {
80 6290 : if (std::forward<T>(t)) {
81 6257 : std::forward<Transform>(f)(*std::forward<T>(t));
82 6257 : }
83 6289 : }
84 : } // namespace iroha
85 :
86 : #endif // IROHA_COMMON_BIND_HPP
|