]>
git.proxmox.com Git - ceph.git/blob - 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
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
18 #include <shared_mutex>
19 #include <type_traits>
22 #include <boost/optional.hpp>
24 #ifndef CEPH_COMMON_CONVENIENCE_H
25 #define CEPH_COMMON_CONVENIENCE_H
28 // boost::optional is wonderful! Unfortunately it lacks a function for
29 // the thing you would most obviously want to do with it: apply a
30 // function to its contents.
32 // There are two obvious candidates. The first is a function that
33 // takes a function and an optional value and returns an optional
34 // value, either holding the return value of the function or holding
37 // I'd considered making more overloads for mutable lvalue
38 // references, but those are going a bit beyond likely use cases.
40 template<typename T
, typename F
>
41 auto maybe_do(const boost::optional
<T
>& t
, F
&& f
) ->
42 boost::optional
<std::result_of_t
<F(const std::decay_t
<T
>)>>
45 return { std::forward
<F
>(f
)(*t
) };
50 // The other obvious function takes an optional but returns an
51 // ‘unwrapped’ value, either the result of evaluating the function or
52 // a provided alternate value.
54 template<typename T
, typename F
, typename U
>
55 auto maybe_do_or(const boost::optional
<T
>& t
, F
&& f
, U
&& u
) ->
56 std::result_of_t
<F(const std::decay_t
<T
>)>
58 static_assert(std::is_convertible_v
<U
, std::result_of_t
<F(T
)>>,
59 "Alternate value must be convertible to function return type.");
61 return std::forward
<F
>(f
)(*t
);
63 return std::forward
<U
>(u
);
67 // Same thing but for std::optional
69 template<typename T
, typename F
>
70 auto maybe_do(const std::optional
<T
>& t
, F
&& f
) ->
71 std::optional
<std::result_of_t
<F(const std::decay_t
<T
>)>>
74 return { std::forward
<F
>(f
)(*t
) };
79 // The other obvious function takes an optional but returns an
80 // ‘unwrapped’ value, either the result of evaluating the function or
81 // a provided alternate value.
83 template<typename T
, typename F
, typename U
>
84 auto maybe_do_or(const std::optional
<T
>& t
, F
&& f
, U
&& u
) ->
85 std::result_of_t
<F(const std::decay_t
<T
>)>
87 static_assert(std::is_convertible_v
<U
, std::result_of_t
<F(T
)>>,
88 "Alternate value must be convertible to function return type.");
90 return std::forward
<F
>(f
)(*t
);
92 return std::forward
<U
>(u
);
95 namespace _convenience
{
96 template<typename
... Ts
, typename F
, std::size_t... Is
>
97 inline void for_each_helper(const std::tuple
<Ts
...>& t
, const F
& f
,
98 std::index_sequence
<Is
...>) {
99 (f(std::get
<Is
>(t
)), ..., void());
101 template<typename
... Ts
, typename F
, std::size_t... Is
>
102 inline void for_each_helper(std::tuple
<Ts
...>& t
, const F
& f
,
103 std::index_sequence
<Is
...>) {
104 (f(std::get
<Is
>(t
)), ..., void());
106 template<typename
... Ts
, typename F
, std::size_t... Is
>
107 inline void for_each_helper(const std::tuple
<Ts
...>& t
, F
& f
,
108 std::index_sequence
<Is
...>) {
109 (f(std::get
<Is
>(t
)), ..., void());
111 template<typename
... Ts
, typename F
, std::size_t... Is
>
112 inline void for_each_helper(std::tuple
<Ts
...>& t
, F
& f
,
113 std::index_sequence
<Is
...>) {
114 (f(std::get
<Is
>(t
)), ..., void());
118 template<typename
... Ts
, typename F
>
119 inline void for_each(const std::tuple
<Ts
...>& t
, const F
& f
) {
120 _convenience::for_each_helper(t
, f
, std::index_sequence_for
<Ts
...>{});
122 template<typename
... Ts
, typename F
>
123 inline void for_each(std::tuple
<Ts
...>& t
, const F
& f
) {
124 _convenience::for_each_helper(t
, f
, std::index_sequence_for
<Ts
...>{});
126 template<typename
... Ts
, typename F
>
127 inline void for_each(const std::tuple
<Ts
...>& t
, F
& f
) {
128 _convenience::for_each_helper(t
, f
, std::index_sequence_for
<Ts
...>{});
130 template<typename
... Ts
, typename F
>
131 inline void for_each(std::tuple
<Ts
...>& t
, F
& f
) {
132 _convenience::for_each_helper(t
, f
, std::index_sequence_for
<Ts
...>{});
135 #endif // CEPH_COMMON_CONVENIENCE_H