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