diff options
author | Michael Lutz <michi@icosahedron.de> | 2021-11-06 23:11:22 +0100 |
---|---|---|
committer | Michael Lutz <michi@icosahedron.de> | 2021-12-16 22:28:32 +0100 |
commit | b0990fcff7358e839468e5cf811ffddc8b9d73e2 (patch) | |
tree | 08da5cbe48d5dcc46e8c539e0da1aa8f6233bad9 /src/core/strong_typedef_type.hpp | |
parent | 4fc055d6e97e76faf53ff3f29e36a4a4549bf6e7 (diff) | |
download | openttd-b0990fcff7358e839468e5cf811ffddc8b9d73e2.tar.xz |
Codechange: Make TileIndex a "strong" typedef to give it a distinct type.
This is accomplished by changing it to a single member struct with the
appropriate operator overloads to make it all work with not too much
source modifications.
Diffstat (limited to 'src/core/strong_typedef_type.hpp')
-rw-r--r-- | src/core/strong_typedef_type.hpp | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp new file mode 100644 index 000000000..b5df28b2f --- /dev/null +++ b/src/core/strong_typedef_type.hpp @@ -0,0 +1,73 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file strong_typedef_type.hpp Type (helpers) for making a strong typedef that is a distinct type. */ + +#ifndef STRONG_TYPEDEF_TYPE_HPP +#define STRONG_TYPEDEF_TYPE_HPP + +/** Non-templated base for #StrongTypedef for use with type trait queries. */ +struct StrongTypedefBase {}; + +/** + * Templated helper to make a type-safe 'typedef' representing a single POD value. + * A normal 'typedef' is not distinct from its base type and will be treated as + * identical in many contexts. This class provides a distinct type that can still + * be assign from and compared to values of its base type. + * + * @note This is meant to be used as a base class, not directly. + * @tparam T Storage type + * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class). + */ +template <class T, class Tthis> +struct StrongTypedef : StrongTypedefBase { + using Type = T; + + T value{}; ///< Backing storage field. + + constexpr StrongTypedef() = default; + constexpr StrongTypedef(const StrongTypedef &o) = default; + constexpr StrongTypedef(StrongTypedef &&o) = default; + + constexpr StrongTypedef(const T &value) : value(value) {} + + constexpr Tthis &operator =(const StrongTypedef &rhs) { this->value = rhs.value; return static_cast<Tthis &>(*this); } + constexpr Tthis &operator =(StrongTypedef &&rhs) { this->value = std::move(rhs.value); return static_cast<Tthis &>(*this); } + constexpr Tthis &operator =(const T &rhs) { this->value = rhs; return static_cast<Tthis &>(*this); } + + explicit constexpr operator T() const { return this->value; } + + constexpr bool operator ==(const StrongTypedef &rhs) const { return this->value == rhs.value; } + constexpr bool operator !=(const StrongTypedef &rhs) const { return this->value != rhs.value; } + constexpr bool operator ==(const T &rhs) const { return this->value == rhs; } + constexpr bool operator !=(const T &rhs) const { return this->value != rhs; } +}; + +/** + * Extension of #StrongTypedef with operators for addition and subtraction. + * @tparam T Storage type + * @tparam Tthis Type of the derived class (i.e. the concrete usage of this class). + */ +template <class T, class Tthis> +struct StrongIntegralTypedef : StrongTypedef<T, Tthis> { + using StrongTypedef<T, Tthis>::StrongTypedef; + + constexpr Tthis &operator ++() { this->value++; return static_cast<Tthis &>(*this); } + constexpr Tthis &operator --() { this->value--; return static_cast<Tthis &>(*this); } + constexpr Tthis operator ++(int) { auto res = static_cast<Tthis &>(*this); this->value++; return res; } + constexpr Tthis operator --(int) { auto res = static_cast<Tthis &>(*this); this->value--; return res; } + + constexpr Tthis &operator +=(const Tthis &rhs) { this->value += rhs.value; return *static_cast<Tthis *>(this); } + constexpr Tthis &operator -=(const Tthis &rhs) { this->value -= rhs.value; return *static_cast<Tthis *>(this); } + + constexpr Tthis operator +(const Tthis &rhs) const { return Tthis{ this->value + rhs.value }; } + constexpr Tthis operator -(const Tthis &rhs) const { return Tthis{ this->value - rhs.value }; } + constexpr Tthis operator +(const T &rhs) const { return Tthis{ this->value + rhs }; } + constexpr Tthis operator -(const T &rhs) const { return Tthis{ this->value - rhs }; } +}; + +#endif /* STRONG_TYPEDEF_TYPE_HPP */ |