Library of Assembled Shared Sources
maybe_none.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2025 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#pragma once
44
45#include "../config/config.h"
46
47namespace lass::python
48{
49
50/** Wrapper to type-hint return values in Python that maybe `None` but not likely.
51 *
52 * Use this class to wrap a type T that could be None in Python (for example, a pointer type),
53 * but it is not likely to be None and forcing the user to expliclitly check for `None` can
54 * more painful than helpful. Annotating the type as `T | MaybeNone` instead of `T | None`
55 * will make static type-checkers like mypy ignore the `None` case, while still allowing
56 * the user to check for `None` if they want to. See [The Any Trick] for more information.
57 *
58 * @note This class does **NOT** prevent `None` values from being passed or returned,
59 * and it does **NOT** provide any runtime or compile-time checks whatsoever.
60 * It only alters the type-hint in Python for static type-checkers.
61 *
62 * MaybeNone<T> types can only be returned from C++ to Python, it doesn't make sense to
63 * have them as function parameters in C++.
64 *
65 * Built-in support for MaybeNone is provided for raw pointers `T*`, util::SharedPtr<T>,
66 * `std::shared_ptr<T>`, and `std::optional<T>`.
67 * To support your own types, you must specialize PyExportTraits, see PyExportTraitsMaybeNone
68 * for more information.
69 *
70 * [The Any Trick]: https://typing.python.org/en/latest/guides/writing_stubs.html#the-any-trick
71 *
72 * @ingroup Python
73 * @sa PyExportTraitsMaybeNone
74 * @sa PyExportTraits<MaybeNone<T*>>
75 * @sa PyExportTraits<MaybeNone<util::SharedPtr<T,S,C>>>
76 * @sa PyExportTraits<MaybeNone<std::shared_ptr<T>>>
77 * @sa PyExportTraits<MaybeNone<std::optional<T>>>
78 * @sa NoNone
79 */
80template <typename T>
81class MaybeNone
82{
83public:
84 MaybeNone(const T& x = T()): value_(x) {}
85 MaybeNone(std::nullptr_t): value_(nullptr) {}
86
87 T& reference() { return value_; } ///< Return reference to wrapped value
88 const T& reference() const { return value_; } ///< Return reference to wrapped value
89
90 operator T&() { return value_; }
91 operator const T&() const { return value_; }
92 auto operator->() const { return value_.operator->(); }
93 auto operator->() { return value_.operator->(); }
94 auto& operator*() const { return value_.operator*(); }
95 auto& operator*() { return value_.operator*(); }
96
97 bool operator!() const { return !value_; }
98 explicit operator bool() const { return static_cast<bool>(value_); }
99
100#if __cpp_impl_three_way_comparison
101 auto operator<=>(const MaybeNone& other) const = default;
102#endif
103
104private:
105 T value_;
106};
107
108#if !__cpp_impl_three_way_comparison
109
110template <typename T> bool operator==(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() == b.reference(); }
111template <typename T> bool operator!=(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() != b.reference(); }
112template <typename T> bool operator<(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() < b.reference(); }
113template <typename T> bool operator>(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() > b.reference(); }
114template <typename T> bool operator<=(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() <= b.reference(); }
115template <typename T> bool operator>=(const MaybeNone<T>& a, const MaybeNone<T>& b) { return a.reference() >= b.reference(); }
116template <typename T> bool operator==(const MaybeNone<T>& a, std::nullptr_t b) { return a.reference() == b; }
117template <typename T> bool operator!=(const MaybeNone<T>& a, std::nullptr_t b) { return a.reference() != b; }
118template <typename T> bool operator==(std::nullptr_t a, const MaybeNone<T>& b) { return a == b.reference(); }
119template <typename T> bool operator!=(std::nullptr_t a, const MaybeNone<T>& b) { return a != b.reference(); }
120
121#endif
122
123}
Wrapper to type-hint return values in Python that maybe None but not likely.
Definition maybe_none.h:82
T & reference()
Return reference to wrapped value.
Definition maybe_none.h:87
const T & reference() const
Return reference to wrapped value.
Definition maybe_none.h:88
Comprehensive C++ to Python binding library.