ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
Loading...
Searching...
No Matches
StrongType.hpp
1#pragma once
2#include <iostream>
3#include <type_traits>
4
6namespace qip {
7
44template <auto enumV, typename BaseT>
45struct StrongType {
46private:
47 static_assert(std::is_arithmetic_v<BaseT>,
48 "StrongType only available for arithmetic types");
49 static_assert(
50 std::is_enum_v<decltype(enumV)>,
51 "StrongType must be instantiated with scoped enum (enum class)");
52 using StrongT = StrongType<enumV, BaseT>; // type alias
53
54public:
55 BaseT v;
56
57 explicit constexpr StrongType(BaseT tv) : v(tv) {}
58 explicit constexpr operator BaseT() const { return v; }
59 constexpr BaseT &as_base() { return v; }
60 [[nodiscard]] constexpr BaseT as_base() const { return v; }
61
63 using BaseType = BaseT;
64
66 constexpr StrongT &operator*=(const StrongT &rhs) {
67 this->v *= rhs.v;
68 return *this;
69 }
70 friend constexpr StrongT operator*(StrongT lhs, const StrongT &rhs) {
71 return lhs *= rhs;
72 }
73 constexpr StrongT &operator/=(const StrongT &rhs) {
74 this->v /= rhs.v;
75 return *this;
76 }
77 friend constexpr StrongT operator/(StrongT lhs, const StrongT &rhs) {
78 return lhs /= rhs;
79 }
80 constexpr StrongT &operator+=(const StrongT &rhs) {
81 this->v += rhs.v;
82 return *this;
83 }
84 friend constexpr StrongT operator+(StrongT lhs, const StrongT &rhs) {
85 return lhs += rhs;
86 }
87 constexpr StrongT &operator-=(const StrongT &rhs) {
88 this->v -= rhs.v;
89 return *this;
90 }
91 friend constexpr StrongT operator-(StrongT lhs, const StrongT &rhs) {
92 return lhs -= rhs;
93 }
94
96 constexpr StrongT &operator*=(const BaseT &rhs) {
97 this->v *= rhs;
98 return *this;
99 }
100 friend constexpr StrongT operator*(StrongT lhs, const BaseT &rhs) {
101 return lhs *= rhs;
102 }
103 friend constexpr StrongT operator*(const BaseT &lhs, StrongT rhs) {
104 return rhs *= lhs;
105 }
107 // If StrongT is used for physical units, this will likely not be what you
108 // want. In this case, just be explicit. Base/Strong is not scalar
109 // multiplication.
110 constexpr StrongT &operator/=(const BaseT &rhs) {
111 this->v /= rhs;
112 return *this;
113 }
114 friend constexpr StrongT operator/(StrongT lhs, const BaseT &rhs) {
115 return lhs /= rhs;
116 }
117
119 constexpr StrongT &operator++() {
120 ++v;
121 return *this;
122 }
123 constexpr StrongT operator++(int) {
124 StrongT result(*this);
125 ++(*this);
126 return result;
127 }
128 constexpr StrongT &operator--() {
129 --v;
130 return *this;
131 }
132 constexpr StrongT operator--(int) {
133 StrongT result(*this);
134 --(*this);
135 return result;
136 }
137
139 friend constexpr bool operator==(const StrongT &lhs, const StrongT &rhs) {
140 return lhs.v == rhs.v;
141 }
142 friend constexpr bool operator!=(const StrongT &lhs, const StrongT &rhs) {
143 return !(lhs == rhs);
144 }
145 friend constexpr bool operator<(const StrongT &lhs, const StrongT &rhs) {
146 return lhs.v < rhs.v;
147 }
148 friend constexpr bool operator>(const StrongT &lhs, const StrongT &rhs) {
149 return rhs < lhs;
150 }
151 friend constexpr bool operator<=(const StrongT &lhs, const StrongT &rhs) {
152 return !(rhs < lhs);
153 }
154 friend constexpr bool operator>=(const StrongT &lhs, const StrongT &rhs) {
155 return !(lhs < rhs);
156 }
157
160 friend constexpr bool operator==(const StrongT &lhs, const BaseT &&rhs) {
161 return lhs.v == rhs;
162 }
163 friend constexpr bool operator!=(const StrongT &lhs, const BaseT &&rhs) {
164 return lhs.v != rhs;
165 }
166 friend constexpr bool operator<(const StrongT &lhs, const BaseT &&rhs) {
167 return lhs.v < rhs;
168 }
169 friend constexpr bool operator>(const StrongT &lhs, const BaseT &&rhs) {
170 return lhs.v > rhs;
171 }
172 friend constexpr bool operator<=(const StrongT &lhs, const BaseT &&rhs) {
173 return lhs.v <= rhs;
174 }
175 friend constexpr bool operator>=(const StrongT &lhs, const BaseT &&rhs) {
176 return lhs.v >= rhs;
177 }
178 friend constexpr bool operator==(const BaseT &&lhs, const StrongT &rhs) {
179 return lhs == rhs.v;
180 }
181 friend constexpr bool operator!=(const BaseT &&lhs, const StrongT &rhs) {
182 return lhs != rhs.v;
183 }
184 friend constexpr bool operator<(const BaseT &&lhs, const StrongT &rhs) {
185 return lhs < rhs.v;
186 }
187 friend constexpr bool operator>(const BaseT &&lhs, const StrongT &rhs) {
188 return lhs > rhs.v;
189 }
190 friend constexpr bool operator<=(const BaseT &&lhs, const StrongT &rhs) {
191 return lhs <= rhs.v;
192 }
193 friend constexpr bool operator>=(const BaseT &&lhs, const StrongT &rhs) {
194 return lhs >= rhs.v;
195 }
196
198 friend std::ostream &operator<<(std::ostream &os, const StrongT &rhs) {
199 return os << rhs.v;
200 }
201 friend std::istream &operator>>(std::istream &is, StrongT &rhs) {
202 return is >> rhs.v;
203 }
204};
205
206} // namespace qip
qip library: A collection of useful functions
Definition Array.hpp:9
A light-weight easy-to-use single-file header-only template class for strong typing.
Definition StrongType.hpp:45
constexpr StrongT & operator*=(const BaseT &rhs)
Provide Base*Strong, Strong*Base oprators - allow scalar multiplication.
Definition StrongType.hpp:96
constexpr StrongT & operator/=(const BaseT &rhs)
Provide Strong/Base, but NOT Base/Strong (still scalar multiplication).
Definition StrongType.hpp:110
constexpr StrongT & operator++()
Provides pre/post increment/decrement (++, –) operators.
Definition StrongType.hpp:119
constexpr StrongT & operator*=(const StrongT &rhs)
Provides operators for regular arithmetic operations.
Definition StrongType.hpp:66
friend std::ostream & operator<<(std::ostream &os, const StrongT &rhs)
Provides iostream interface, works as it would for BaseT.
Definition StrongType.hpp:198
friend constexpr bool operator==(const StrongT &lhs, const BaseT &&rhs)
Provides operators for direct comparison w/ BaseT literal (rvalue). Note: Does not allow comparison w...
Definition StrongType.hpp:160
friend constexpr bool operator==(const StrongT &lhs, const StrongT &rhs)
Provides comparison operators.
Definition StrongType.hpp:139
BaseT BaseType
makes 'BaseType' publicly accessible
Definition StrongType.hpp:63