]>
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 #include "include/ceph_assert.h" // I despise you. Not you the reader, I'm talking
25 // to the include file.
28 #ifndef CEPH_COMMON_CONVENIENCE_H
29 #define CEPH_COMMON_CONVENIENCE_H
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.
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
41 // I'd considered making more overloads for mutable lvalue
42 // references, but those are going a bit beyond likely use cases.
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
>)>>
49 return { std::forward
<F
>(f
)(*t
) };
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.
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
>)>
62 static_assert(std::is_convertible_v
<U
, std::result_of_t
<F(T
)>>,
63 "Alternate value must be convertible to function return type.");
65 return std::forward
<F
>(f
)(*t
);
67 return std::forward
<U
>(u
);
71 // Same thing but for std::optional
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
>)>>
78 return { std::forward
<F
>(f
)(*t
) };
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.
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
>)>
91 static_assert(std::is_convertible_v
<U
, std::result_of_t
<F(T
)>>,
92 "Alternate value must be convertible to function return type.");
94 return std::forward
<F
>(f
)(*t
);
96 return std::forward
<U
>(u
);
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());
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());
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());
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());
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
...>{});
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
...>{});
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
...>{});
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
...>{});
139 #endif // CEPH_COMMON_CONVENIENCE_H