From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/common/convenience.h | 135 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/common/convenience.h (limited to 'src/common/convenience.h') diff --git a/src/common/convenience.h b/src/common/convenience.h new file mode 100644 index 000000000..db803c59d --- /dev/null +++ b/src/common/convenience.h @@ -0,0 +1,135 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#ifndef CEPH_COMMON_CONVENIENCE_H +#define CEPH_COMMON_CONVENIENCE_H + +namespace ceph { +// boost::optional is wonderful! Unfortunately it lacks a function for +// the thing you would most obviously want to do with it: apply a +// function to its contents. + +// There are two obvious candidates. The first is a function that +// takes a function and an optional value and returns an optional +// value, either holding the return value of the function or holding +// nothing. +// +// I'd considered making more overloads for mutable lvalue +// references, but those are going a bit beyond likely use cases. +// +template +auto maybe_do(const boost::optional& t, F&& f) -> + boost::optional)>> +{ + if (t) + return { std::forward(f)(*t) }; + else + return boost::none; +} + +// The other obvious function takes an optional but returns an +// ‘unwrapped’ value, either the result of evaluating the function or +// a provided alternate value. +// +template +auto maybe_do_or(const boost::optional& t, F&& f, U&& u) -> + std::result_of_t)> +{ + static_assert(std::is_convertible_v>, + "Alternate value must be convertible to function return type."); + if (t) + return std::forward(f)(*t); + else + return std::forward(u); +} + + +// Same thing but for std::optional + +template +auto maybe_do(const std::optional& t, F&& f) -> + std::optional)>> +{ + if (t) + return { std::forward(f)(*t) }; + else + return std::nullopt; +} + +// The other obvious function takes an optional but returns an +// ‘unwrapped’ value, either the result of evaluating the function or +// a provided alternate value. +// +template +auto maybe_do_or(const std::optional& t, F&& f, U&& u) -> + std::result_of_t)> +{ + static_assert(std::is_convertible_v>, + "Alternate value must be convertible to function return type."); + if (t) + return std::forward(f)(*t); + else + return std::forward(u); +} + +namespace _convenience { +template +inline void for_each_helper(const std::tuple& t, const F& f, + std::index_sequence) { + (f(std::get(t)), ..., void()); +} +template +inline void for_each_helper(std::tuple& t, const F& f, + std::index_sequence) { + (f(std::get(t)), ..., void()); +} +template +inline void for_each_helper(const std::tuple& t, F& f, + std::index_sequence) { + (f(std::get(t)), ..., void()); +} +template +inline void for_each_helper(std::tuple& t, F& f, + std::index_sequence) { + (f(std::get(t)), ..., void()); +} +} + +template +inline void for_each(const std::tuple& t, const F& f) { + _convenience::for_each_helper(t, f, std::index_sequence_for{}); +} +template +inline void for_each(std::tuple& t, const F& f) { + _convenience::for_each_helper(t, f, std::index_sequence_for{}); +} +template +inline void for_each(const std::tuple& t, F& f) { + _convenience::for_each_helper(t, f, std::index_sequence_for{}); +} +template +inline void for_each(std::tuple& t, F& f) { + _convenience::for_each_helper(t, f, std::index_sequence_for{}); +} +} +#endif // CEPH_COMMON_CONVENIENCE_H -- cgit v1.2.3