The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
optional_reference.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 - 2025
3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY.
11
12 See the COPYING file for more details.
13*/
14
15#pragma once
16
17#include <functional>
19
20namespace utils
21{
22/**
23 * A simple wrapper class for optional reference types.
24 *
25 * Since utils::optional (as of C++17 at least) does not support reference types (see [1]),
26 * the only way to use those is utils::optional<std::reference_wrapper<T>>. However, this makes
27 * the interace messy, as to access the referenced object you need an extra get() call to
28 * access the value stored in the reference wrapper.
29 *
30 * This rebinds operator=() as boost::optional does. Assigning a value to this wrapper will
31 * simply change the object to which it points instead of assigning a value to the referenced
32 * object. To change the value of the referenced object, perform an assignment on value()
33 * or operator*.
34 *
35 * [1] https://www.fluentcpp.com/2018/10/05/pros-cons-optional-references/
36 */
37template<typename T>
39{
40public:
41 optional_reference() = default;
42
44 : opt_(ref)
45 {
46 }
47
48 optional_reference(utils::nullopt_t)
49 : opt_()
50 {
51 }
52
53 T& value() const
54 {
55#ifndef __APPLE__
56 return opt_.value().get();
57#else
58 if(opt_) {
59 return opt_->get();
60 } else {
61 // We're going to drop this codepath once we can use optional::value anyway, but just
62 // noting we want this function to ultimately throw utils::bad_optional_access.
63 throw std::runtime_error("Optional reference has no value");
64 }
65#endif
66 }
67
69 {
70 opt_ = new_ref;
71 return *this;
72 }
73
74 explicit operator bool() const
75 {
76 return opt_.has_value();
77 }
78
79 /** Returns a pointer to the referenced object or nullptr if no reference is held. */
80 T* ptr() const
81 {
82 if(opt_) {
83 return &value();
84 } else {
85 return nullptr;
86 }
87 }
88
89 T* operator->() const
90 {
91 return &value();
92 }
93
94 T& operator*() const
95 {
96 return value();
97 }
98
99private:
100 utils::optional<std::reference_wrapper<T>> opt_;
101};
102
103} // namespace utils
A simple wrapper class for optional reference types.
optional_reference(utils::nullopt_t)
utils::optional< std::reference_wrapper< T > > opt_
T * ptr() const
Returns a pointer to the referenced object or nullptr if no reference is held.
optional_reference< T > & operator=(T &new_ref)