Botan 3.8.1
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 <botan/concepts.h>
13
14#include <iosfwd>
15#include <span>
16#include <string>
17
18namespace Botan {
19
20/**
21 * Added as an additional "capability tag" to enable arithmetic operators with
22 * plain numbers for Strong<> types that wrap a number.
23 */
25
26namespace detail {
27
28/**
29 * Checks whether the @p CapabilityT is included in the @p Tags type pack.
30 */
31template <typename CapabilityT, typename... Tags>
32constexpr bool has_capability = (std::is_same_v<CapabilityT, Tags> || ...);
33
34template <typename T>
36 private:
37 T m_value;
38
39 public:
40 using wrapped_type = T;
41
42 public:
43 Strong_Base() = default;
44 Strong_Base(const Strong_Base&) = default;
45 Strong_Base(Strong_Base&&) noexcept = default;
46 Strong_Base& operator=(const Strong_Base&) = default;
47 Strong_Base& operator=(Strong_Base&&) noexcept = default;
48
49 constexpr explicit Strong_Base(T v) : m_value(std::move(v)) {}
50
51 constexpr T& get() & { return m_value; }
52
53 constexpr const T& get() const& { return m_value; }
54
55 constexpr T&& get() && { return std::move(m_value); }
56
57 constexpr const T&& get() const&& { return std::move(m_value); }
58};
59
60template <typename T>
61class Strong_Adapter : public Strong_Base<T> {
62 public:
64};
65
66template <std::integral T>
67class Strong_Adapter<T> : public Strong_Base<T> {
68 public:
70};
71
72template <concepts::container T>
74 public:
75 using value_type = typename T::value_type;
76 using size_type = typename T::size_type;
77 using iterator = typename T::iterator;
78 using const_iterator = typename T::const_iterator;
79
80 public:
82
86
87 template <typename InputIt>
89
90 public:
91 decltype(auto) begin() noexcept(noexcept(this->get().begin())) { return this->get().begin(); }
92
93 decltype(auto) begin() const noexcept(noexcept(this->get().begin())) { return this->get().begin(); }
94
95 decltype(auto) end() noexcept(noexcept(this->get().end())) { return this->get().end(); }
96
97 decltype(auto) end() const noexcept(noexcept(this->get().end())) { return this->get().end(); }
98
99 decltype(auto) cbegin() noexcept(noexcept(this->get().cbegin())) { return this->get().cbegin(); }
100
101 decltype(auto) cbegin() const noexcept(noexcept(this->get().cbegin())) { return this->get().cbegin(); }
102
103 decltype(auto) cend() noexcept(noexcept(this->get().cend())) { return this->get().cend(); }
104
105 decltype(auto) cend() const noexcept(noexcept(this->get().cend())) { return this->get().cend(); }
106
107 size_type size() const noexcept(noexcept(this->get().size())) { return this->get().size(); }
108
109 bool empty() const noexcept(noexcept(this->get().empty()))
110 requires(concepts::has_empty<T>)
111 {
112 return this->get().empty();
113 }
114
115 void resize(size_type size) noexcept(noexcept(this->get().resize(size)))
117 {
118 this->get().resize(size);
119 }
120
121 void reserve(size_type size) noexcept(noexcept(this->get().reserve(size)))
123 {
124 this->get().reserve(size);
125 }
126
127 template <typename U>
128 decltype(auto) operator[](U&& i) const noexcept(noexcept(this->get().operator[](i))) {
129 return this->get()[std::forward<U>(i)];
130 }
131
132 template <typename U>
133 decltype(auto) operator[](U&& i) noexcept(noexcept(this->get().operator[](i))) {
134 return this->get()[std::forward<U>(i)];
135 }
136
137 template <typename U>
138 decltype(auto) at(U&& i) const noexcept(noexcept(this->get().at(i)))
140 {
141 return this->get().at(std::forward<U>(i));
142 }
143
144 template <typename U>
145 decltype(auto) at(U&& i) noexcept(noexcept(this->get().at(i)))
147 {
148 return this->get().at(std::forward<U>(i));
149 }
150};
151
152template <concepts::container T>
153class Strong_Adapter<T> : public Container_Strong_Adapter_Base<T> {
154 public:
155 using Container_Strong_Adapter_Base<T>::Container_Strong_Adapter_Base;
156};
157
158template <concepts::contiguous_container T>
159class Strong_Adapter<T> : public Container_Strong_Adapter_Base<T> {
160 public:
161 using pointer = typename T::pointer;
162 using const_pointer = typename T::const_pointer;
163
164 public:
166
167 explicit Strong_Adapter(std::span<const typename Container_Strong_Adapter_Base<T>::value_type> span) :
168 Strong_Adapter(T(span.begin(), span.end())) {}
169
170 // Disambiguates the usage of string literals, otherwise:
171 // Strong_Adapter(std::span<>) and Strong_Adapter(const char*)
172 // would be ambiguous.
173 explicit Strong_Adapter(const char* str)
174 requires(std::same_as<T, std::string>)
175 : Strong_Adapter(std::string(str)) {}
176
177 public:
178 decltype(auto) data() noexcept(noexcept(this->get().data())) { return this->get().data(); }
179
180 decltype(auto) data() const noexcept(noexcept(this->get().data())) { return this->get().data(); }
181};
182
183} // namespace detail
184
185/**
186 * Strong types can be used as wrappers around common types to provide
187 * compile time semantics. They usually contribute to more maintainable and
188 * less error-prone code especially when dealing with function parameters.
189 *
190 * Internally, this provides adapters so that the wrapping strong type behaves
191 * as much as the underlying type as possible and desirable.
192 *
193 * This implementation was inspired by:
194 * https://stackoverflow.com/a/69030899
195 */
196template <typename T, typename TagTypeT, typename... Capabilities>
198 public:
200
201 template <typename CapabilityT>
202 constexpr static bool has_capability() {
203 return (std::is_same_v<CapabilityT, Capabilities> || ...);
204 }
205
206 private:
207 using Tag = TagTypeT;
208};
209
210/**
211 * @brief Generically unwraps a strong type to its underlying type.
212 *
213 * If the provided type is not a strong type, it is returned as is.
214 *
215 * @note This is meant as a helper for generic code that needs to deal with both
216 * wrapped strong types and bare objects. Use the ordinary `get()` method
217 * if you know that you are dealing with a strong type.
218 *
219 * @param t value to be unwrapped
220 * @return the unwrapped value
221 */
222template <typename T>
223[[nodiscard]] constexpr decltype(auto) unwrap_strong_type(T&& t) {
225 // If the parameter type isn't a strong type, return it as is.
226 return std::forward<T>(t);
227 } else {
228 // Unwrap the strong type and return the underlying value.
229 return std::forward<T>(t).get();
230 }
231}
232
233/**
234 * @brief Wraps a value into a caller-defined (strong) type.
235 *
236 * If the provided object @p t is already of type @p T, it is returned as is.
237 *
238 * @note This is meant as a helper for generic code that needs to deal with both
239 * wrapped strong types and bare objects. Use the ordinary constructor if
240 * you know that you are dealing with a bare value type.
241 *
242 * @param t value to be wrapped
243 * @return the wrapped value
244 */
245template <typename T, typename ParamT>
246 requires std::constructible_from<T, ParamT> ||
247 (concepts::strong_type<T> && std::constructible_from<typename T::wrapped_type, ParamT>)
248[[nodiscard]] constexpr decltype(auto) wrap_strong_type(ParamT&& t) {
249 if constexpr(std::same_as<std::remove_cvref_t<ParamT>, T>) {
250 // Noop, if the parameter type already is the desired return type.
251 return std::forward<ParamT>(t);
252 } else if constexpr(std::constructible_from<T, ParamT>) {
253 // Implicit conversion from the parameter type to the return type.
254 return T{std::forward<ParamT>(t)};
255 } else {
256 // Explicitly calling the wrapped type's constructor to support
257 // implicit conversions on types that mark their constructors as explicit.
258 static_assert(concepts::strong_type<T> && std::constructible_from<typename T::wrapped_type, ParamT>);
259 return T{typename T::wrapped_type{std::forward<ParamT>(t)}};
260 }
261}
262
263namespace detail {
264
265template <typename T>
267 using type = T;
268};
269
270template <concepts::strong_type T>
272 using type = typename T::wrapped_type;
273};
274
275} // namespace detail
276
277/**
278 * @brief Extracts the wrapped type from a strong type.
279 *
280 * If the provided type is not a strong type, it is returned as is.
281 *
282 * @note This is meant as a helper for generic code that needs to deal with both
283 * wrapped strong types and bare objects. Use the ordinary `::wrapped_type`
284 * declaration if you know that you are dealing with a strong type.
285 */
286template <typename T>
288
289template <typename T, typename... Tags>
291decltype(auto) operator<<(std::ostream& os, const Strong<T, Tags...>& v) {
292 return os << v.get();
293}
294
295template <typename T, typename... Tags>
296 requires(std::equality_comparable<T>)
297bool operator==(const Strong<T, Tags...>& lhs, const Strong<T, Tags...>& rhs) {
298 return lhs.get() == rhs.get();
299}
300
301template <typename T, typename... Tags>
302 requires(std::three_way_comparable<T>)
304 return lhs.get() <=> rhs.get();
305}
306
307template <std::integral T1, std::integral T2, typename... Tags>
309 return a <=> b.get();
310}
311
312template <std::integral T1, std::integral T2, typename... Tags>
314 return a.get() <=> b;
315}
316
317template <std::integral T1, std::integral T2, typename... Tags>
319 return a == b.get();
320}
321
322template <std::integral T1, std::integral T2, typename... Tags>
324 return a.get() == b;
325}
326
327template <std::integral T1, std::integral T2, typename... Tags>
328 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
329constexpr decltype(auto) operator+(T1 a, Strong<T2, Tags...> b) {
330 return Strong<T2, Tags...>(a + b.get());
331}
332
333template <std::integral T1, std::integral T2, typename... Tags>
334 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
335constexpr decltype(auto) operator+(Strong<T1, Tags...> a, T2 b) {
336 return Strong<T1, Tags...>(a.get() + b);
337}
338
339template <std::integral T, typename... Tags>
340constexpr decltype(auto) operator+(Strong<T, Tags...> a, Strong<T, Tags...> b) {
341 return Strong<T, Tags...>(a.get() + b.get());
342}
343
344template <std::integral T1, std::integral T2, typename... Tags>
345 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
346constexpr decltype(auto) operator-(T1 a, Strong<T2, Tags...> b) {
347 return Strong<T2, Tags...>(a - b.get());
348}
349
350template <std::integral T1, std::integral T2, typename... Tags>
351 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
352constexpr decltype(auto) operator-(Strong<T1, Tags...> a, T2 b) {
353 return Strong<T1, Tags...>(a.get() - b);
354}
355
356template <std::integral T, typename... Tags>
357constexpr decltype(auto) operator-(Strong<T, Tags...> a, Strong<T, Tags...> b) {
358 return Strong<T, Tags...>(a.get() - b.get());
359}
360
361template <std::integral T1, std::integral T2, typename... Tags>
362 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
363constexpr decltype(auto) operator*(T1 a, Strong<T2, Tags...> b) {
364 return Strong<T2, Tags...>(a * b.get());
365}
366
367template <std::integral T1, std::integral T2, typename... Tags>
368 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
369constexpr decltype(auto) operator*(Strong<T1, Tags...> a, T2 b) {
370 return Strong<T1, Tags...>(a.get() * b);
371}
372
373template <std::integral T, typename... Tags>
374constexpr decltype(auto) operator*(Strong<T, Tags...> a, Strong<T, Tags...> b) {
375 return Strong<T, Tags...>(a.get() * b.get());
376}
377
378template <std::integral T1, std::integral T2, typename... Tags>
379 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
380constexpr decltype(auto) operator/(T1 a, Strong<T2, Tags...> b) {
381 return Strong<T2, Tags...>(a / b.get());
382}
383
384template <std::integral T1, std::integral T2, typename... Tags>
385 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
386constexpr decltype(auto) operator/(Strong<T1, Tags...> a, T2 b) {
387 return Strong<T1, Tags...>(a.get() / b);
388}
389
390template <std::integral T, typename... Tags>
391constexpr decltype(auto) operator/(Strong<T, Tags...> a, Strong<T, Tags...> b) {
392 return Strong<T, Tags...>(a.get() / b.get());
393}
394
395template <std::integral T1, std::integral T2, typename... Tags>
396 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
397constexpr decltype(auto) operator^(T1 a, Strong<T2, Tags...> b) {
398 return Strong<T2, Tags...>(a ^ b.get());
399}
400
401template <std::integral T1, std::integral T2, typename... Tags>
402 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
403constexpr decltype(auto) operator^(Strong<T1, Tags...> a, T2 b) {
404 return Strong<T1, Tags...>(a.get() ^ b);
405}
406
407template <std::integral T, typename... Tags>
408constexpr decltype(auto) operator^(Strong<T, Tags...> a, Strong<T, Tags...> b) {
409 return Strong<T, Tags...>(a.get() ^ b.get());
410}
411
412template <std::integral T1, std::integral T2, typename... Tags>
413 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
414constexpr decltype(auto) operator&(T1 a, Strong<T2, Tags...> b) {
415 return Strong<T2, Tags...>(a & b.get());
416}
417
418template <std::integral T1, std::integral T2, typename... Tags>
419 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
420constexpr decltype(auto) operator&(Strong<T1, Tags...> a, T2 b) {
421 return Strong<T1, Tags...>(a.get() & b);
422}
423
424template <std::integral T, typename... Tags>
425constexpr decltype(auto) operator&(Strong<T, Tags...> a, Strong<T, Tags...> b) {
426 return Strong<T, Tags...>(a.get() & b.get());
427}
428
429template <std::integral T1, std::integral T2, typename... Tags>
430 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
431constexpr decltype(auto) operator|(T1 a, Strong<T2, Tags...> b) {
432 return Strong<T2, Tags...>(a | b.get());
433}
434
435template <std::integral T1, std::integral T2, typename... Tags>
436 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
437constexpr decltype(auto) operator|(Strong<T1, Tags...> a, T2 b) {
438 return Strong<T1, Tags...>(a.get() | b);
439}
440
441template <std::integral T, typename... Tags>
442constexpr decltype(auto) operator|(Strong<T, Tags...> a, Strong<T, Tags...> b) {
443 return Strong<T, Tags...>(a.get() | b.get());
444}
445
446template <std::integral T1, std::integral T2, typename... Tags>
447 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
448constexpr decltype(auto) operator>>(T1 a, Strong<T2, Tags...> b) {
449 return Strong<T2, Tags...>(a >> b.get());
450}
451
452template <std::integral T1, std::integral T2, typename... Tags>
453 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
454constexpr decltype(auto) operator>>(Strong<T1, Tags...> a, T2 b) {
455 return Strong<T1, Tags...>(a.get() >> b);
456}
457
458template <std::integral T, typename... Tags>
459constexpr decltype(auto) operator>>(Strong<T, Tags...> a, Strong<T, Tags...> b) {
460 return Strong<T, Tags...>(a.get() >> b.get());
461}
462
463template <std::integral T1, std::integral T2, typename... Tags>
464 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
465constexpr decltype(auto) operator<<(T1 a, Strong<T2, Tags...> b) {
466 return Strong<T2, Tags...>(a << b.get());
467}
468
469template <std::integral T1, std::integral T2, typename... Tags>
470 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
471constexpr decltype(auto) operator<<(Strong<T1, Tags...> a, T2 b) {
472 return Strong<T1, Tags...>(a.get() << b);
473}
474
475template <std::integral T, typename... Tags>
476constexpr decltype(auto) operator<<(Strong<T, Tags...> a, Strong<T, Tags...> b) {
477 return Strong<T, Tags...>(a.get() << b.get());
478}
479
480template <std::integral T1, std::integral T2, typename... Tags>
481 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
482constexpr auto operator+=(Strong<T1, Tags...>& a, T2 b) {
483 a.get() += b;
484 return a;
485}
486
487template <std::integral T, typename... Tags>
489 a.get() += b.get();
490 return a;
491}
492
493template <std::integral T1, std::integral T2, typename... Tags>
494 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
495constexpr auto operator-=(Strong<T1, Tags...>& a, T2 b) {
496 a.get() -= b;
497 return a;
498}
499
500template <std::integral T, typename... Tags>
502 a.get() -= b.get();
503 return a;
504}
505
506template <std::integral T1, std::integral T2, typename... Tags>
507 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
508constexpr auto operator*=(Strong<T1, Tags...>& a, T2 b) {
509 a.get() *= b;
510 return a;
511}
512
513template <std::integral T, typename... Tags>
515 a.get() *= b.get();
516 return a;
517}
518
519template <std::integral T1, std::integral T2, typename... Tags>
520 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
521constexpr auto operator/=(Strong<T1, Tags...>& a, T2 b) {
522 a.get() /= b;
523 return a;
524}
525
526template <std::integral T, typename... Tags>
528 a.get() /= b.get();
529 return a;
530}
531
532template <std::integral T1, std::integral T2, typename... Tags>
533 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
534constexpr auto operator^=(Strong<T1, Tags...>& a, T2 b) {
535 a.get() ^= b;
536 return a;
537}
538
539template <std::integral T, typename... Tags>
541 a.get() ^= b.get();
542 return a;
543}
544
545template <std::integral T1, std::integral T2, typename... Tags>
546 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
547constexpr auto operator&=(Strong<T1, Tags...>& a, T2 b) {
548 a.get() &= b;
549 return a;
550}
551
552template <std::integral T, typename... Tags>
554 a.get() &= b.get();
555 return a;
556}
557
558template <std::integral T1, std::integral T2, typename... Tags>
559 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
560constexpr auto operator|=(Strong<T1, Tags...>& a, T2 b) {
561 a.get() |= b;
562 return a;
563}
564
565template <std::integral T, typename... Tags>
567 a.get() |= b.get();
568 return a;
569}
570
571template <std::integral T1, std::integral T2, typename... Tags>
572 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
573constexpr auto operator>>=(Strong<T1, Tags...>& a, T2 b) {
574 a.get() >>= b;
575 return a;
576}
577
578template <std::integral T, typename... Tags>
580 a.get() >>= b.get();
581 return a;
582}
583
584template <std::integral T1, std::integral T2, typename... Tags>
585 requires(detail::has_capability<EnableArithmeticWithPlainNumber, Tags...>)
586constexpr auto operator<<=(Strong<T1, Tags...>& a, T2 b) {
587 a.get() <<= b;
588 return a;
589}
590
591template <std::integral T, typename... Tags>
593 a.get() <<= b.get();
594 return a;
595}
596
597template <std::integral T, typename... Tags>
598constexpr auto operator++(Strong<T, Tags...>& a, int) {
599 auto tmp = a;
600 ++a.get();
601 return tmp;
602}
603
604template <std::integral T, typename... Tags>
605constexpr auto operator++(Strong<T, Tags...>& a) {
606 ++a.get();
607 return a;
608}
609
610template <std::integral T, typename... Tags>
611constexpr auto operator--(Strong<T, Tags...>& a, int) {
612 auto tmp = a;
613 --a.get();
614 return tmp;
615}
616
617template <std::integral T, typename... Tags>
618constexpr auto operator--(Strong<T, Tags...>& a) {
619 --a.get();
620 return a;
621}
622
623/**
624 * This mimmicks a std::span but keeps track of the strong-type information. Use
625 * this when you would want to use `const Strong<...>&` as a parameter
626 * declaration. In particular this allows assigning strong-type information to
627 * slices of a bigger buffer without copying the bytes. E.g:
628 *
629 * using Foo = Strong<std::vector<uint8_t>, Foo_>;
630 *
631 * void bar(StrongSpan<Foo> foo) { ... }
632 *
633 * std::vector<uint8_t> buffer;
634 * BufferSlicer slicer(buffer);
635 * bar(slicer.take<Foo>()); // This does not copy the data from buffer but
636 * // just annotates the 'Foo' strong-type info.
637 */
638template <concepts::contiguous_strong_type T>
640 using underlying_span = std::
641 conditional_t<std::is_const_v<T>, std::span<const typename T::value_type>, std::span<typename T::value_type>>;
642
643 public:
644 using value_type = typename underlying_span::value_type;
645 using size_type = typename underlying_span::size_type;
646 using iterator = typename underlying_span::iterator;
647 using pointer = typename underlying_span::pointer;
648 using const_pointer = typename underlying_span::const_pointer;
649
650 StrongSpan() = default;
651
652 explicit StrongSpan(underlying_span span) : m_span(span) {}
653
654 StrongSpan(T& strong) : m_span(strong) {}
655
656 // Allows implicit conversion from `StrongSpan<T>` to `StrongSpan<const T>`.
657 // Note that this is not bi-directional. Conversion from `StrongSpan<const T>`
658 // to `StrongSpan<T>` is not allowed.
659 //
660 // TODO: Technically, we should be able to phrase this with a `requires std::is_const_v<T>`
661 // instead of the `std::enable_if` constructions. clang-tidy (14 or 15) doesn't seem
662 // to pick up on that (yet?). As a result, for a non-const T it assumes this to be
663 // a declaration of an ordinary copy constructor. The existance of a copy constructor
664 // is interpreted as "not cheap to copy", setting off the `performance-unnecessary-value-param` check.
665 // See also: https://github.com/randombit/botan/issues/3591
667 typename = std::enable_if_t<std::is_same_v<T2, std::remove_const_t<T>>>>
668 StrongSpan(const StrongSpan<T2>& other) : m_span(other.get()) {}
669
670 StrongSpan(const StrongSpan& other) = default;
671
672 ~StrongSpan() = default;
673
674 /**
675 * @returns the underlying std::span without any type constraints
676 */
677 underlying_span get() const { return m_span; }
678
679 /**
680 * @returns the underlying std::span without any type constraints
681 */
682 underlying_span get() { return m_span; }
683
684 decltype(auto) data() noexcept(noexcept(this->m_span.data())) { return this->m_span.data(); }
685
686 decltype(auto) data() const noexcept(noexcept(this->m_span.data())) { return this->m_span.data(); }
687
688 decltype(auto) size() const noexcept(noexcept(this->m_span.size())) { return this->m_span.size(); }
689
690 bool empty() const noexcept(noexcept(this->m_span.empty())) { return this->m_span.empty(); }
691
692 decltype(auto) begin() noexcept(noexcept(this->m_span.begin())) { return this->m_span.begin(); }
693
694 decltype(auto) begin() const noexcept(noexcept(this->m_span.begin())) { return this->m_span.begin(); }
695
696 decltype(auto) end() noexcept(noexcept(this->m_span.end())) { return this->m_span.end(); }
697
698 decltype(auto) end() const noexcept(noexcept(this->m_span.end())) { return this->m_span.end(); }
699
700 decltype(auto) operator[](typename underlying_span::size_type i) const noexcept { return this->m_span[i]; }
701
702 private:
703 underlying_span m_span;
704};
705
706template <typename>
707struct is_strong_span : std::false_type {};
708
709template <typename T>
710struct is_strong_span<StrongSpan<T>> : std::true_type {};
711
712template <typename T>
714
715} // namespace Botan
716
717#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()
decltype(auto) operator[](typename underlying_span::size_type i) const noexcept
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) cbegin() const noexcept(noexcept(this->get().cbegin()))
decltype(auto) begin() noexcept(noexcept(this->get().begin()))
Definition strong_type.h:91
Container_Strong_Adapter_Base(InputIt begin, InputIt end)
Definition strong_type.h:88
decltype(auto) cend() noexcept(noexcept(this->get().cend()))
decltype(auto) cend() const noexcept(noexcept(this->get().cend()))
decltype(auto) end() const noexcept(noexcept(this->get().end()))
Definition strong_type.h:97
void reserve(size_type size) noexcept(noexcept(this->get().reserve(size)))
size_type size() const noexcept(noexcept(this->get().size()))
decltype(auto) at(U &&i) noexcept(noexcept(this->get().at(i)))
decltype(auto) end() noexcept(noexcept(this->get().end()))
Definition strong_type.h:95
bool empty() const noexcept(noexcept(this->get().empty()))
decltype(auto) begin() const noexcept(noexcept(this->get().begin()))
Definition strong_type.h:93
void resize(size_type size) noexcept(noexcept(this->get().resize(size)))
typename T::const_iterator const_iterator
Definition strong_type.h:78
decltype(auto) at(U &&i) const noexcept(noexcept(this->get().at(i)))
decltype(auto) cbegin() noexcept(noexcept(this->get().cbegin()))
Definition strong_type.h:99
decltype(auto) data() const noexcept(noexcept(this->get().data()))
decltype(auto) data() noexcept(noexcept(this->get().data()))
typename T::const_pointer const_pointer
Strong_Adapter(std::span< const typename Container_Strong_Adapter_Base< T >::value_type > span)
constexpr const T & get() const &
Definition strong_type.h:53
Strong_Base(Strong_Base &&) noexcept=default
constexpr T & get() &
Definition strong_type.h:51
constexpr const T && get() const &&
Definition strong_type.h:57
constexpr T && get() &&
Definition strong_type.h:55
Strong_Base(const Strong_Base &)=default
constexpr bool has_capability
Definition strong_type.h:32
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:330
BigInt operator/(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:95
BigInt operator-(const BigInt &x, const BigInt &y)
Definition bigint.h:1095
constexpr auto operator/=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator|=(Strong< T1, Tags... > &a, T2 b)
constexpr decltype(auto) unwrap_strong_type(T &&t)
Generically unwraps a strong type to its underlying type.
constexpr auto operator<<=(Strong< T1, Tags... > &a, T2 b)
constexpr auto operator&=(Strong< T1, Tags... > &a, T2 b)
typename detail::wrapped_type_helper< std::remove_cvref_t< T > >::type strong_type_wrapped_type
Extracts the wrapped type from a strong type.
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:448
constexpr decltype(auto) wrap_strong_type(ParamT &&t)
Wraps a value into a caller-defined (strong) type.
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:87
int operator>>(int fd, Pipe &pipe)
Definition fd_unix.cpp:39
constexpr auto operator-=(Strong< T1, Tags... > &a, T2 b)
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:70
constexpr auto operator*=(Strong< T1, Tags... > &a, T2 b)