]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/convenience.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / common / convenience.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include <mutex>
16 #include <memory>
17 #include <optional>
18 #include <shared_mutex>
19 #include <type_traits>
20 #include <utility>
21
22 #include <boost/optional.hpp>
23
24 #include "include/ceph_assert.h" // I despise you. Not you the reader, I'm talking
25 // to the include file.
26
27
28 #ifndef CEPH_COMMON_CONVENIENCE_H
29 #define CEPH_COMMON_CONVENIENCE_H
30
31 namespace ceph {
32 // boost::optional is wonderful! Unfortunately it lacks a function for
33 // the thing you would most obviously want to do with it: apply a
34 // function to its contents.
35
36 // There are two obvious candidates. The first is a function that
37 // takes a function and an optional value and returns an optional
38 // value, either holding the return value of the function or holding
39 // nothing.
40 //
41 // I'd considered making more overloads for mutable lvalue
42 // references, but those are going a bit beyond likely use cases.
43 //
44 template<typename T, typename F>
45 auto maybe_do(const boost::optional<T>& t, F&& f) ->
46 boost::optional<std::result_of_t<F(const std::decay_t<T>)>>
47 {
48 if (t)
49 return { std::forward<F>(f)(*t) };
50 else
51 return boost::none;
52 }
53
54 // The other obvious function takes an optional but returns an
55 // ‘unwrapped’ value, either the result of evaluating the function or
56 // a provided alternate value.
57 //
58 template<typename T, typename F, typename U>
59 auto maybe_do_or(const boost::optional<T>& t, F&& f, U&& u) ->
60 std::result_of_t<F(const std::decay_t<T>)>
61 {
62 static_assert(std::is_convertible_v<U, std::result_of_t<F(T)>>,
63 "Alternate value must be convertible to function return type.");
64 if (t)
65 return std::forward<F>(f)(*t);
66 else
67 return std::forward<U>(u);
68 }
69
70
71 // Same thing but for std::optional
72
73 template<typename T, typename F>
74 auto maybe_do(const std::optional<T>& t, F&& f) ->
75 std::optional<std::result_of_t<F(const std::decay_t<T>)>>
76 {
77 if (t)
78 return { std::forward<F>(f)(*t) };
79 else
80 return std::nullopt;
81 }
82
83 // The other obvious function takes an optional but returns an
84 // ‘unwrapped’ value, either the result of evaluating the function or
85 // a provided alternate value.
86 //
87 template<typename T, typename F, typename U>
88 auto maybe_do_or(const std::optional<T>& t, F&& f, U&& u) ->
89 std::result_of_t<F(const std::decay_t<T>)>
90 {
91 static_assert(std::is_convertible_v<U, std::result_of_t<F(T)>>,
92 "Alternate value must be convertible to function return type.");
93 if (t)
94 return std::forward<F>(f)(*t);
95 else
96 return std::forward<U>(u);
97 }
98
99 namespace _convenience {
100 template<typename... Ts, typename F, std::size_t... Is>
101 inline void for_each_helper(const std::tuple<Ts...>& t, const F& f,
102 std::index_sequence<Is...>) {
103 (f(std::get<Is>(t)), ..., void());
104 }
105 template<typename... Ts, typename F, std::size_t... Is>
106 inline void for_each_helper(std::tuple<Ts...>& t, const F& f,
107 std::index_sequence<Is...>) {
108 (f(std::get<Is>(t)), ..., void());
109 }
110 template<typename... Ts, typename F, std::size_t... Is>
111 inline void for_each_helper(const std::tuple<Ts...>& t, F& f,
112 std::index_sequence<Is...>) {
113 (f(std::get<Is>(t)), ..., void());
114 }
115 template<typename... Ts, typename F, std::size_t... Is>
116 inline void for_each_helper(std::tuple<Ts...>& t, F& f,
117 std::index_sequence<Is...>) {
118 (f(std::get<Is>(t)), ..., void());
119 }
120 }
121
122 template<typename... Ts, typename F>
123 inline void for_each(const std::tuple<Ts...>& t, const F& f) {
124 _convenience::for_each_helper(t, f, std::index_sequence_for<Ts...>{});
125 }
126 template<typename... Ts, typename F>
127 inline void for_each(std::tuple<Ts...>& t, const F& f) {
128 _convenience::for_each_helper(t, f, std::index_sequence_for<Ts...>{});
129 }
130 template<typename... Ts, typename F>
131 inline void for_each(const std::tuple<Ts...>& t, F& f) {
132 _convenience::for_each_helper(t, f, std::index_sequence_for<Ts...>{});
133 }
134 template<typename... Ts, typename F>
135 inline void for_each(std::tuple<Ts...>& t, F& f) {
136 _convenience::for_each_helper(t, f, std::index_sequence_for<Ts...>{});
137 }
138 }
139 #endif // CEPH_COMMON_CONVENIENCE_H