Botan 3.5.0
Crypto and TLS for C&
strong_type.h
Go to the documentation of this file.
1/**
2 * A wrapper class to implement strong types
3 * (C) 2022 Jack Lloyd
4 * 2022 René Meusel - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#ifndef BOTAN_STRONG_TYPE_H_
10#define BOTAN_STRONG_TYPE_H_
11
12#include <ostream>
13#include <span>
14
15#include <botan/concepts.h>
16
17namespace Botan {
18
19/**
20 * Added as an additional "capability tag" to enable arithmetic operators with
21 * plain numbers for Strong<> types that wrap a number.
22 */
24
25namespace detail {
26
27/**
28 * Checks whether the @p CapabilityT is included in the @p Tags type pack.
29 */
30template <typename CapabilityT, typename... Tags>
31constexpr bool has_capability = (std::is_same_v<CapabilityT, Tags> || ...);
32
33template <typename T>
35 private:
36 T m_value;
37
38 public:
39 using wrapped_type = T;
40
41 public:
42 Strong_Base() = default;
43 Strong_Base(const Strong_Base&) = default;
44 Strong_Base(Strong_Base&&) noexcept = default;
45 Strong_Base& operator=(const Strong_Base&) = default;
46 Strong_Base& operator=(Strong_Base&&) noexcept = default;
47
48 constexpr explicit Strong_Base(T v) : m_value(std::move(v)) {}
49
50 T& get() { return m_value; }
51
52 const T& get() const { return m_value; }
53};
54
55template <typename T>
56class Strong_Adapter : public Strong_Base<T> {
57 public:
59};
60
61template <std::integral T>
62class Strong_Adapter<T> : public Strong_Base<T> {
63 public:
65};
66
67template <concepts::container T>
68class Strong_Adapter<T> : public Strong_Base<T> {
69 public:
70 using value_type = typename T::value_type;
71 using size_type = typename T::size_type;
72 using iterator = typename T::iterator;
73 using const_iterator = typename T::const_iterator;
74 using pointer = typename T::pointer;
75 using const_pointer = typename T::const_pointer;
76
77 public:
79
80 explicit Strong_Adapter(std::span<const value_type> span)
82 : Strong_Adapter(T(span.begin(), span.end())) {}
83
84 explicit Strong_Adapter(size_t size)
86 : Strong_Adapter(T(size)) {}
87
88 template <typename InputIt>
89 Strong_Adapter(InputIt begin, InputIt end) : Strong_Adapter(T(begin, end)) {}
90
91 // Disambiguates the usage of string literals, otherwise:
92 // Strong_Adapter(std::span<>) and Strong_Adapter(const char*)
93 // would be ambiguous.
94 explicit Strong_Adapter(const char* str)
95 requires(std::same_as<T, std::string>)
96 : Strong_Adapter(std::string(str)) {}
97
98 public:
99 decltype(auto) begin() noexcept(noexcept(this->get().begin())) { return this->get().begin(); }
100
101 decltype(auto) begin() const noexcept(noexcept(this->get().begin())) { return this->get().begin(); }
102
103 decltype(auto) end() noexcept(noexcept(this->get().end())) { return this->get().end(); }
104
105 decltype(auto) end() const noexcept(noexcept(this->get().end())) { return this->get().end(); }
106
107 decltype(auto) cbegin() noexcept(noexcept(this->get().cbegin())) { return this->get().cbegin(); }
108
109 decltype(auto) cbegin() const noexcept(noexcept(this->get().cbegin())) { return this->get().cbegin(); }
110
111 decltype(auto) cend() noexcept(noexcept(this->get().cend())) { return this->get().cend(); }
112
113 decltype(auto) cend() const noexcept(noexcept(this->get().cend())) { return this->get().cend(); }
114
115 size_type size() const noexcept(noexcept(this->get().size())) { return this->get().size(); }
116
117 decltype(auto) data() noexcept(noexcept(this->get().data()))
119 {
120 return this->get().data();
121 }
122
123 decltype(auto) data() const noexcept(noexcept(this->get().data()))
125 {
126 return this->get().data();
127 }
128
129 bool empty() const noexcept(noexcept(this->get().empty()))
130 requires(concepts::has_empty<T>)
131 {
132 return this->get().empty();
133 }
134
135 void resize(size_type size) noexcept(noexcept(this->get().resize(size)))
137 {
138 this->get().resize(size);
139 }
140
141 void reserve(size_type size) noexcept(noexcept(this->get().reserve(size)))
143 {
144 this->get().reserve(size);
145 }
146
147 decltype(auto) operator[](size_type i) const noexcept(noexcept(this->get().operator[](i))) {
148 return this->get()[i];
149 }
150
151 decltype(auto) operator[](size_type i) noexcept(noexcept(this->get().operator[](i))) { return this->get()[i]; }
152};
153
154} // namespace detail
155
156/**
157 * Strong types can be used as wrappers around common types to provide
158 * compile time semantics. They usually contribute to more maintainable and
159 * less error-prone code especially when dealing with function parameters.
160 *
161 * Internally, this provides adapters so that the wrapping strong type behaves
162 * as much as the underlying type as possible and desirable.
163 *
164 * This implementation was inspired by:
165 * https://stackoverflow.com/a/69030899
166 */
167template <typename T, typename TagTypeT, typename... Capabilities>
169 public:
171
172 template <typename CapabilityT>
173 constexpr static bool has_capability() {
174 return (std::is_same_v<CapabilityT, Capabilities> || ...);
175 }
176
177 private:
178 using Tag = TagTypeT;
179};
180
181/**
182 * Opportunistically unpacks a strong type to its underlying type. If the
183 * provided type is not a strong type, it is returned as is.
184 */
185template <typename T>
186constexpr decltype(auto) unpack(T& t) {
188 return t.get();
189 } else {
190 return t;
191 }
192}
193
194template <typename T, typename... Tags>
195 requires(concepts::streamable<T>)
196decltype(auto) operator<<(std::ostream& os, const Strong<T, Tags...>& v) {
197 return os << v.get();
198}
199
200template <typename T, typename... Tags>
201 requires(std::equality_comparable<T>)
202bool operator==(const Strong<T, Tags...>& lhs, const Strong<T, Tags...>& rhs) {
203 return lhs.get() == rhs.get();
204}
205
206template <typename T, typename... Tags>
207 requires(std::three_way_comparable<T>)
209 return lhs.get() <=> rhs.get();
210}
211
212template <std::integral T1, std::integral T2, typename... Tags>
214 return a <=> b.get();
215}
216
217template <std::integral T1, std::integral T2, typename... Tags>
219 return a.get() <=> b;
220}
221
222template <std::integral T1, std::integral T2, typename... Tags>
224 return a == b.get();
225}
226
227template <std::integral T1, std::integral T2, typename... Tags>
229 return a.get() == b;
230}
231
232template <std::integral T1, std::integral T2, typename... Tags>
233 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
234constexpr decltype(auto) operator+(T1 a, Strong<T2, Tags...> b) {
235 return Strong<T2, Tags...>(a + b.get());
236}
237
238template <std::integral T1, std::integral T2, typename... Tags>
239 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
240constexpr decltype(auto) operator+(Strong<T1, Tags...> a, T2 b) {
241 return Strong<T1, Tags...>(a.get() + b);
242}
243
244template <std::integral T, typename... Tags>
245constexpr decltype(auto) operator+(Strong<T, Tags...> a, Strong<T, Tags...> b) {
246 return Strong<T, Tags...>(a.get() + b.get());
247}
248
249template <std::integral T1, std::integral T2, typename... Tags>
250 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
251constexpr decltype(auto) operator-(T1 a, Strong<T2, Tags...> b) {
252 return Strong<T2, Tags...>(a - b.get());
253}
254
255template <std::integral T1, std::integral T2, typename... Tags>
256 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
257constexpr decltype(auto) operator-(Strong<T1, Tags...> a, T2 b) {
258 return Strong<T1, Tags...>(a.get() - b);
259}
260
261template <std::integral T, typename... Tags>
262constexpr decltype(auto) operator-(Strong<T, Tags...> a, Strong<T, Tags...> b) {
263 return Strong<T, Tags...>(a.get() - b.get());
264}
265
266template <std::integral T1, std::integral T2, typename... Tags>
267 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
268constexpr decltype(auto) operator*(T1 a, Strong<T2, Tags...> b) {
269 return Strong<T2, Tags...>(a * b.get());
270}
271
272template <std::integral T1, std::integral T2, typename... Tags>
273 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
274constexpr decltype(auto) operator*(Strong<T1, Tags...> a, T2 b) {
275 return Strong<T1, Tags...>(a.get() * b);
276}
277
278template <std::integral T, typename... Tags>
279constexpr decltype(auto) operator*(Strong<T, Tags...> a, Strong<T, Tags...> b) {
280 return Strong<T, Tags...>(a.get() * b.get());
281}
282
283template <std::integral T1, std::integral T2, typename... Tags>
284 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
285constexpr decltype(auto) operator/(T1 a, Strong<T2, Tags...> b) {
286 return Strong<T2, Tags...>(a / b.get());
287}
288
289template <std::integral T1, std::integral T2, typename... Tags>
290 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
291constexpr decltype(auto) operator/(Strong<T1, Tags...> a, T2 b) {
292 return Strong<T1, Tags...>(a.get() / b);
293}
294
295template <std::integral T, typename... Tags>
296constexpr decltype(auto) operator/(Strong<T, Tags...> a, Strong<T, Tags...> b) {
297 return Strong<T, Tags...>(a.get() / b.get());
298}
299
300template <std::integral T1, std::integral T2, typename... Tags>
301 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
302constexpr decltype(auto) operator^(T1 a, Strong<T2, Tags...> b) {
303 return Strong<T2, Tags...>(a ^ b.get());
304}
305
306template <std::integral T1, std::integral T2, typename... Tags>
307 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
308constexpr decltype(auto) operator^(Strong<T1, Tags...> a, T2 b) {
309 return Strong<T1, Tags...>(a.get() ^ b);
310}
311
312template <std::integral T, typename... Tags>
313constexpr decltype(auto) operator^(Strong<T, Tags...> a, Strong<T, Tags...> b) {
314 return Strong<T, Tags...>(a.get() ^ b.get());
315}
316
317template <std::integral T1, std::integral T2, typename... Tags>
318 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
319constexpr decltype(auto) operator&(T1 a, Strong<T2, Tags...> b) {
320 return Strong<T2, Tags...>(a & b.get());
321}
322
323template <std::integral T1, std::integral T2, typename... Tags>
324 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
325constexpr decltype(auto) operator&(Strong<T1, Tags...> a, T2 b) {
326 return Strong<T1, Tags...>(a.get() & b);
327}
328
329template <std::integral T, typename... Tags>
330constexpr decltype(auto) operator&(Strong<T, Tags...> a, Strong<T, Tags...> b) {
331 return Strong<T, Tags...>(a.get() & b.get());
332}
333
334template <std::integral T1, std::integral T2, typename... Tags>
335 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
336constexpr decltype(auto) operator|(T1 a, Strong<T2, Tags...> b) {
337 return Strong<T2, Tags...>(a | b.get());
338}
339
340template <std::integral T1, std::integral T2, typename... Tags>
341 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
342constexpr decltype(auto) operator|(Strong<T1, Tags...> a, T2 b) {
343 return Strong<T1, Tags...>(a.get() | b);
344}
345
346template <std::integral T, typename... Tags>
347constexpr decltype(auto) operator|(Strong<T, Tags...> a, Strong<T, Tags...> b) {
348 return Strong<T, Tags...>(a.get() | b.get());
349}
350
351template <std::integral T1, std::integral T2, typename... Tags>
352 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
353constexpr decltype(auto) operator>>(T1 a, Strong<T2, Tags...> b) {
354 return Strong<T2, Tags...>(a >> b.get());
355}
356
357template <std::integral T1, std::integral T2, typename... Tags>
358 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
359constexpr decltype(auto) operator>>(Strong<T1, Tags...> a, T2 b) {
360 return Strong<T1, Tags...>(a.get() >> b);
361}
362
363template <std::integral T, typename... Tags>
364constexpr decltype(auto) operator>>(Strong<T, Tags...> a, Strong<T, Tags...> b) {
365 return Strong<T, Tags...>(a.get() >> b.get());
366}
367
368template <std::integral T1, std::integral T2, typename... Tags>
369 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
370constexpr decltype(auto) operator<<(T1 a, Strong<T2, Tags...> b) {
371 return Strong<T2, Tags...>(a << b.get());
372}
373
374template <std::integral T1, std::integral T2, typename... Tags>
375 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
376constexpr decltype(auto) operator<<(Strong<T1, Tags...> a, T2 b) {
377 return Strong<T1, Tags...>(a.get() << b);
378}
379
380template <std::integral T, typename... Tags>
381constexpr decltype(auto) operator<<(Strong<T, Tags...> a, Strong<T, Tags...> b) {
382 return Strong<T, Tags...>(a.get() << b.get());
383}
384
385template <std::integral T1, std::integral T2, typename... Tags>
386 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
387constexpr auto operator+=(Strong<T1, Tags...>& a, T2 b) {
388 a.get() += b;
389 return a;
390}
391
392template <std::integral T, typename... Tags>
394 a.get() += b.get();
395 return a;
396}
397
398template <std::integral T1, std::integral T2, typename... Tags>
399 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
400constexpr auto operator-=(Strong<T1, Tags...>& a, T2 b) {
401 a.get() -= b;
402 return a;
403}
404
405template <std::integral T, typename... Tags>
407 a.get() -= b.get();
408 return a;
409}
410
411template <std::integral T1, std::integral T2, typename... Tags>
412 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
413constexpr auto operator*=(Strong<T1, Tags...>& a, T2 b) {
414 a.get() *= b;
415 return a;
416}
417
418template <std::integral T, typename... Tags>
420 a.get() *= b.get();
421 return a;
422}
423
424template <std::integral T1, std::integral T2, typename... Tags>
425 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
426constexpr auto operator/=(Strong<T1, Tags...>& a, T2 b) {
427 a.get() /= b;
428 return a;
429}
430
431template <std::integral T, typename... Tags>
433 a.get() /= b.get();
434 return a;
435}
436
437template <std::integral T1, std::integral T2, typename... Tags>
438 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
439constexpr auto operator^=(Strong<T1, Tags...>& a, T2 b) {
440 a.get() ^= b;
441 return a;
442}
443
444template <std::integral T, typename... Tags>
446 a.get() ^= b.get();
447 return a;
448}
449
450template <std::integral T1, std::integral T2, typename... Tags>
451 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
452constexpr auto operator&=(Strong<T1, Tags...>& a, T2 b) {
453 a.get() &= b;
454 return a;
455}
456
457template <std::integral T, typename... Tags>
459 a.get() &= b.get();
460 return a;
461}
462
463template <std::integral T1, std::integral T2, typename... Tags>
464 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
465constexpr auto operator|=(Strong<T1, Tags...>& a, T2 b) {
466 a.get() |= b;
467 return a;
468}
469
470template <std::integral T, typename... Tags>
472 a.get() |= b.get();
473 return a;
474}
475
476template <std::integral T1, std::integral T2, typename... Tags>
477 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
478constexpr auto operator>>=(Strong<T1, Tags...>& a, T2 b) {
479 a.get() >>= b;
480 return a;
481}
482
483template <std::integral T, typename... Tags>
485 a.get() >>= b.get();
486 return a;
487}
488
489template <std::integral T1, std::integral T2, typename... Tags>
490 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
491constexpr auto operator<<=(Strong<T1, Tags...>& a, T2 b) {
492 a.get() <<= b;
493 return a;
494}
495
496template <std::integral T, typename... Tags>
498 a.get() <<= b.get();
499 return a;
500}
501
502template <std::integral T, typename... Tags>
503constexpr auto operator++(Strong<T, Tags...>& a, int) {
504 auto tmp = a;
505 ++a.get();
506 return tmp;
507}
508
509template <std::integral T, typename... Tags>
510constexpr auto operator++(Strong<T, Tags...>& a) {
511 ++a.get();
512 return a;
513}
514
515template <std::integral T, typename... Tags>
516constexpr auto operator--(Strong<T, Tags...>& a, int) {
517 auto tmp = a;
518 --a.get();
519 return tmp;
520}
521
522template <std::integral T, typename... Tags>
523constexpr auto operator--(Strong<T, Tags...>& a) {
524 --a.get();
525 return a;
526}
527
528/**
529 * This mimmicks a std::span but keeps track of the strong-type information. Use
530 * this when you would want to use `const Strong<...>&` as a parameter
531 * declaration. In particular this allows assigning strong-type information to
532 * slices of a bigger buffer without copying the bytes. E.g:
533 *
534 * using Foo = Strong<std::vector<uint8_t>, Foo_>;
535 *
536 * void bar(StrongSpan<Foo> foo) { ... }
537 *
538 * std::vector<uint8_t> buffer;
539 * BufferSlicer slicer(buffer);
540 * bar(slicer.take<Foo>()); // This does not copy the data from buffer but
541 * // just annotates the 'Foo' strong-type info.
542 */
543template <concepts::contiguous_strong_type T>
545 using underlying_span = std::
546 conditional_t<std::is_const_v<T>, std::span<const typename T::value_type>, std::span<typename T::value_type>>;
547
548 public:
549 using value_type = typename underlying_span::value_type;
550 using size_type = typename underlying_span::size_type;
551 using iterator = typename underlying_span::iterator;
552 using pointer = typename underlying_span::pointer;
553 using const_pointer = typename underlying_span::const_pointer;
554
555 StrongSpan() = default;
556
557 explicit StrongSpan(underlying_span span) : m_span(span) {}
558
559 StrongSpan(T& strong) : m_span(strong) {}
560
561 // Allows implicit conversion from `StrongSpan<T>` to `StrongSpan<const T>`.
562 // Note that this is not bi-directional. Conversion from `StrongSpan<const T>`
563 // to `StrongSpan<T>` is not allowed.
564 //
565 // TODO: Technically, we should be able to phrase this with a `requires std::is_const_v<T>`
566 // instead of the `std::enable_if` constructions. clang-tidy (14 or 15) doesn't seem
567 // to pick up on that (yet?). As a result, for a non-const T it assumes this to be
568 // a declaration of an ordinary copy constructor. The existance of a copy constructor
569 // is interpreted as "not cheap to copy", setting off the `performance-unnecessary-value-param` check.
570 // See also: https://github.com/randombit/botan/issues/3591
572 typename = std::enable_if_t<std::is_same_v<T2, std::remove_const_t<T>>>>
573 StrongSpan(const StrongSpan<T2>& other) : m_span(other.get()) {}
574
575 StrongSpan(const StrongSpan& other) = default;
576
577 ~StrongSpan() = default;
578
579 /**
580 * @returns the underlying std::span without any type constraints
581 */
582 underlying_span get() const { return m_span; }
583
584 /**
585 * @returns the underlying std::span without any type constraints
586 */
587 underlying_span get() { return m_span; }
588
589 decltype(auto) data() noexcept(noexcept(this->m_span.data())) { return this->m_span.data(); }
590
591 decltype(auto) data() const noexcept(noexcept(this->m_span.data())) { return this->m_span.data(); }
592
593 decltype(auto) size() const noexcept(noexcept(this->m_span.size())) { return this->m_span.size(); }
594
595 bool empty() const noexcept(noexcept(this->m_span.empty())) { return this->m_span.empty(); }
596
597 decltype(auto) begin() noexcept(noexcept(this->m_span.begin())) { return this->m_span.begin(); }
598
599 decltype(auto) begin() const noexcept(noexcept(this->m_span.begin())) { return this->m_span.begin(); }
600
601 decltype(auto) end() noexcept(noexcept(this->m_span.end())) { return this->m_span.end(); }
602
603 decltype(auto) end() const noexcept(noexcept(this->m_span.end())) { return this->m_span.end(); }
604
605 decltype(auto) operator[](typename underlying_span::size_type i) const noexcept { return this->m_span[i]; }
606
607 private:
608 underlying_span m_span;
609};
610
611template <typename>
612struct is_strong_span : std::false_type {};
613
614template <typename T>
615struct is_strong_span<StrongSpan<T>> : std::true_type {};
616
617template <typename T>
619
620} // namespace Botan
621
622#endif
typename underlying_span::size_type size_type
decltype(auto) begin() noexcept(noexcept(this->m_span.begin()))
StrongSpan()=default
decltype(auto) data() noexcept(noexcept(this->m_span.data()))
underlying_span get() const
StrongSpan(const StrongSpan< T2 > &other)
StrongSpan(T &strong)
typename underlying_span::value_type value_type
~StrongSpan()=default
decltype(auto) begin() const noexcept(noexcept(this->m_span.begin()))
StrongSpan(const StrongSpan &other)=default
decltype(auto) end() noexcept(noexcept(this->m_span.end()))
StrongSpan(underlying_span span)
typename underlying_span::const_pointer const_pointer
bool empty() const noexcept(noexcept(this->m_span.empty()))
underlying_span get()
typename underlying_span::pointer pointer
decltype(auto) data() const noexcept(noexcept(this->m_span.data()))
decltype(auto) end() const noexcept(noexcept(this->m_span.end()))
typename underlying_span::iterator iterator
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
static constexpr bool has_capability()
decltype(auto) data() const noexcept(noexcept(this->get().data()))
typename T::size_type size_type
Definition strong_type.h:71
decltype(auto) end() const noexcept(noexcept(this->get().end()))
void resize(size_type size) noexcept(noexcept(this->get().resize(size)))
typename T::iterator iterator
Definition strong_type.h:72
void reserve(size_type size) noexcept(noexcept(this->get().reserve(size)))
decltype(auto) begin() noexcept(noexcept(this->get().begin()))
Definition strong_type.h:99
size_type size() const noexcept(noexcept(this->get().size()))
decltype(auto) cbegin() noexcept(noexcept(this->get().cbegin()))
typename T::const_pointer const_pointer
Definition strong_type.h:75
typename T::value_type value_type
Definition strong_type.h:70
decltype(auto) begin() const noexcept(noexcept(this->get().begin()))
decltype(auto) cend() const noexcept(noexcept(this->get().cend()))
decltype(auto) end() noexcept(noexcept(this->get().end()))
typename T::const_iterator const_iterator
Definition strong_type.h:73
bool empty() const noexcept(noexcept(this->get().empty()))
decltype(auto) data() noexcept(noexcept(this->get().data()))
Strong_Adapter(std::span< const value_type > span)
Definition strong_type.h:80
decltype(auto) cend() noexcept(noexcept(this->get().cend()))
decltype(auto) cbegin() const noexcept(noexcept(this->get().cbegin()))
Strong_Adapter(InputIt begin, InputIt end)
Definition strong_type.h:89
const T & get() const
Definition strong_type.h:52
Strong_Base(Strong_Base &&) noexcept=default
Strong_Base(const Strong_Base &)=default
FE_25519 T
Definition ge.cpp:34
constexpr bool has_capability
Definition strong_type.h:31
ASN1_Type operator|(ASN1_Type x, ASN1_Type y)
Definition asn1_obj.h:75
BigInt operator*(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:46
constexpr auto operator>>=(Strong< T1, Tags... > &a, T2 b)
OctetString operator^(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:109
OctetString operator+(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:99
constexpr auto operator++(Strong< T, Tags... > &a, int)
std::ostream & operator<<(std::ostream &out, const OID &oid)
Definition asn1_obj.h:322
BigInt operator/(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:95
BigInt operator-(const BigInt &x, const BigInt &y)
Definition bigint.h:1089
constexpr auto operator/=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator|=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator<<=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator&=(Strong< T1, Tags... > &a, T2 b)
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition alg_id.cpp:54
std::vector< uint8_t, Alloc > & operator^=(std::vector< uint8_t, Alloc > &out, const std::vector< uint8_t, Alloc2 > &in)
Definition mem_ops.h:445
constexpr bool is_strong_span_v
std::vector< T, Alloc > & operator+=(std::vector< T, Alloc > &out, const std::vector< T, Alloc2 > &in)
Definition secmem.h:80
int operator>>(int fd, Pipe &pipe)
Definition fd_unix.cpp:39
constexpr auto operator-=(Strong< T1, Tags... > &a, T2 b)
constexpr decltype(auto) unpack(T &t)
constexpr auto operator--(Strong< T, Tags... > &a, int)
auto operator<=>(const Strong< T, Tags... > &lhs, const Strong< T, Tags... > &rhs)
ECIES_Flags operator&(ECIES_Flags a, ECIES_Flags b)
Definition ecies.h:50
constexpr auto operator*=(Strong< T1, Tags... > &a, T2 b)