userver: userver/utils/get_if.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
get_if.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/get_if.hpp
4/// @brief @copybrief utils::GetIf
5/// @ingroup userver_universal
6
7#include <functional>
8#include <memory>
9#include <utility>
10
11#include <userver/utils/meta_light.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace utils {
16
17namespace impl {
18
19template <typename T>
20using IsPointerLike =
21 decltype(std::declval<T&>() ? std::addressof(*std::declval<T&&>())
22 : nullptr);
23
24template <typename T>
25inline constexpr bool kIsPointerLike = meta::kIsDetected<IsPointerLike, T>;
26
27} // namespace impl
28
29template <typename Leaf>
30constexpr auto* GetIf(Leaf&& leaf) {
31 if constexpr (impl::kIsPointerLike<Leaf>) {
32 return leaf ? utils::GetIf(*std::forward<Leaf>(leaf)) : nullptr;
33 } else {
34 return std::addressof(std::forward<Leaf>(leaf));
35 }
36}
37
38/// @brief Dereferences a chain of indirections and compositions,
39/// returns nullptr if one of the chain elements is not set
40///
41/// @snippet universal/src/utils/get_if_test.cpp Sample Usage
42template <typename Root, typename Head, typename... Tail>
43constexpr auto* GetIf(Root&& root, Head&& head, Tail&&... tail) {
44 if constexpr (impl::kIsPointerLike<Root>) {
45 return root ? utils::GetIf(*std::forward<Root>(root),
46 std::forward<Head>(head),
47 std::forward<Tail>(tail)...)
48 : nullptr;
49 } else {
50 return utils::GetIf(
51 std::invoke(std::forward<Head>(head), std::forward<Root>(root)),
52 std::forward<Tail>(tail)...);
53 }
54}
55
56} // namespace utils
57
58USERVER_NAMESPACE_END