11#include <initializer_list>
19#include "gw/concepts.hpp"
26struct strong_type_empty_base {
27 constexpr auto operator<=>(
const strong_type_empty_base&)
const noexcept -> std::strong_ordering =
default;
43template <
typename T,
typename Tag>
45 :
public std::conditional_t<std::ranges::range<T>, std::ranges::view_interface<strong_type<T, Tag>>,
46 detail::strong_type_empty_base> {
60 template <
typename... Args>
62 requires std::constructible_from<value_type, Args...>
66 template <
typename U,
typename... Args>
67 constexpr strong_type(std::initializer_list<U> ilist, Args&&... args)
noexcept(
68 std::is_nothrow_constructible_v<value_type, std::initializer_list<U>&, Args...>)
69 requires std::constructible_from<
value_type, std::initializer_list<U>&, Args...>
84 constexpr auto operator->() const noexcept -> const
value_type* {
return &m_value; }
108 constexpr auto value() const&& noexcept -> const
value_type&& {
return std::move(m_value); }
118 template <
typename F>
120 requires std::invocable<F, const value_type&>
126 template <
typename F>
128 requires std::invocable<F, value_type&>
134 template <
typename F>
136 requires std::invocable<F, const value_type&&>
139 func(std::move(m_value))};
143 template <
typename F>
145 requires std::invocable<F, value_type&&>
155 constexpr void swap(
strong_type& rhs)
noexcept(std::is_nothrow_swappable_v<value_type>)
156 requires std::swappable<value_type>
159 swap(m_value, rhs.m_value);
170 template <
typename... Args>
172 requires std::constructible_from<value_type, Args...>
174 m_value =
value_type{std::forward<Args>(args)...};
184 requires std::equality_comparable<value_type>
186 return m_value == rhs.m_value;
190 constexpr auto operator!=(
const strong_type& rhs)
const&
noexcept(
noexcept(m_value != rhs.m_value)) ->
bool
191 requires std::equality_comparable<value_type>
193 return m_value != rhs.m_value;
198 requires std::totally_ordered<value_type>
200 return m_value < rhs.m_value;
205 requires std::totally_ordered<value_type>
207 return m_value > rhs.m_value;
211 constexpr auto operator<=(
const strong_type& rhs)
const&
noexcept(
noexcept(m_value <= rhs.m_value)) ->
bool
212 requires std::totally_ordered<value_type>
214 return m_value <= rhs.m_value;
218 constexpr auto operator>=(
const strong_type& rhs)
const&
noexcept(
noexcept(m_value >= rhs.m_value)) ->
bool
219 requires std::totally_ordered<value_type>
221 return m_value >= rhs.m_value;
225 constexpr auto operator<=>(
const strong_type& rhs)
const&
noexcept(
noexcept(m_value <=>
226 rhs.m_value)) -> std::strong_ordering
227 requires std::three_way_comparable<value_type>
229 return m_value <=> rhs.m_value;
237 constexpr explicit operator const value_type&()
const&
noexcept {
return m_value; }
240 constexpr explicit operator value_type&() &
noexcept {
return m_value; }
243 constexpr explicit operator const value_type&&()
const&&
noexcept {
return std::move(m_value); }
246 constexpr explicit operator value_type&&() &&
noexcept {
return std::move(m_value); }
265 return std::move(*
this);
295 return std::move(*
this);
325 requires std::signed_integral<value_type>
339 requires std::signed_integral<value_type>
485 constexpr auto operator+=(
const strong_type& rhs) &
noexcept(
noexcept(m_value += rhs.m_value)) ->
strong_type&
488 m_value += rhs.m_value;
493 constexpr auto operator+=(strong_type&& rhs) &
noexcept(
noexcept(m_value += rhs.m_value)) -> strong_type&
494 requires arithmetic<value_type>
496 m_value += rhs.m_value;
501 constexpr auto operator-=(
const strong_type& rhs) &
noexcept(
noexcept(m_value -= rhs.m_value)) ->
strong_type&
502 requires arithmetic<value_type>
504 m_value -= rhs.m_value;
509 constexpr auto operator-=(strong_type&& rhs) &
noexcept(
noexcept(m_value -= rhs.m_value)) ->
strong_type&
510 requires arithmetic<value_type>
512 m_value -= rhs.m_value;
517 constexpr auto operator*=(
const strong_type& rhs) &
noexcept(
noexcept(m_value *= rhs.m_value)) ->
strong_type&
518 requires arithmetic<value_type>
520 m_value *= rhs.m_value;
525 constexpr auto operator*=(strong_type&& rhs) &
noexcept(
noexcept(m_value *= rhs.m_value)) ->
strong_type&
526 requires arithmetic<value_type>
528 m_value *= rhs.m_value;
533 constexpr auto operator/=(
const strong_type& rhs) &
noexcept(
noexcept(m_value /= rhs.m_value)) ->
strong_type&
534 requires arithmetic<value_type>
536 m_value /= rhs.m_value;
541 constexpr auto operator/=(strong_type&& rhs) &
noexcept(
noexcept(m_value /= rhs.m_value)) ->
strong_type&
542 requires arithmetic<value_type>
544 m_value /= rhs.m_value;
549 constexpr auto operator%=(
const strong_type& rhs) &
noexcept(
noexcept(m_value %= rhs.m_value)) ->
strong_type&
550 requires arithmetic<value_type>
552 m_value %= rhs.m_value;
557 constexpr auto operator%=(strong_type&& rhs) &
noexcept(
noexcept(m_value %= rhs.m_value)) ->
strong_type&
558 requires arithmetic<value_type>
560 m_value %= rhs.m_value;
577 requires std::unsigned_integral<value_type>
584 requires std::unsigned_integral<value_type>
591 requires std::unsigned_integral<value_type>
598 requires std::unsigned_integral<value_type>
605 requires std::unsigned_integral<value_type>
612 requires std::unsigned_integral<value_type>
619 requires std::unsigned_integral<value_type>
626 requires std::unsigned_integral<value_type>
633 requires std::unsigned_integral<value_type>
640 requires std::unsigned_integral<value_type>
647 requires std::unsigned_integral<value_type>
654 requires std::unsigned_integral<value_type>
661 requires std::unsigned_integral<value_type>
668 requires std::unsigned_integral<value_type>
675 requires std::unsigned_integral<value_type>
682 requires std::unsigned_integral<value_type>
689 requires std::unsigned_integral<value_type>
696 requires std::unsigned_integral<value_type>
703 requires std::unsigned_integral<value_type>
710 requires std::unsigned_integral<value_type>
716 constexpr auto operator&=(
const strong_type& rhs) &
noexcept(
noexcept(m_value &= rhs.m_value)) ->
strong_type&
717 requires std::unsigned_integral<value_type>
719 m_value &= rhs.m_value;
724 constexpr auto operator&=(strong_type&& rhs) &
noexcept(
noexcept(m_value &= rhs.m_value)) -> strong_type&
725 requires std::unsigned_integral<value_type>
727 m_value &= rhs.m_value;
732 constexpr auto operator|=(
const strong_type& rhs) &
noexcept(
noexcept(m_value |= rhs.m_value)) ->
strong_type&
733 requires std::unsigned_integral<value_type>
735 m_value |= rhs.m_value;
740 constexpr auto operator|=(strong_type&& rhs) &
noexcept(
noexcept(m_value |= rhs.m_value)) ->
strong_type&
741 requires std::unsigned_integral<value_type>
743 m_value |= rhs.m_value;
748 constexpr auto operator^=(
const strong_type& rhs) &
noexcept(
noexcept(m_value ^= rhs.m_value)) ->
strong_type&
749 requires std::unsigned_integral<value_type>
751 m_value ^= rhs.m_value;
756 constexpr auto operator^=(strong_type&& rhs) &
noexcept(
noexcept(m_value ^= rhs.m_value)) ->
strong_type&
757 requires std::unsigned_integral<value_type>
759 m_value ^= rhs.m_value;
764 constexpr auto operator<<=(
const strong_type& rhs) &
noexcept(
noexcept(m_value <<= rhs.m_value)) ->
strong_type&
765 requires std::unsigned_integral<value_type>
767 m_value <<= rhs.m_value;
772 constexpr auto operator<<=(strong_type&& rhs) &
noexcept(
noexcept(m_value <<= rhs.m_value)) ->
strong_type&
773 requires std::unsigned_integral<value_type>
775 m_value <<= rhs.m_value;
780 constexpr auto operator>>=(
const strong_type& rhs) &
noexcept(
noexcept(m_value >>= rhs.m_value)) ->
strong_type&
781 requires std::unsigned_integral<value_type>
783 m_value >>= rhs.m_value;
788 constexpr auto operator>>=(strong_type&& rhs) &
noexcept(
noexcept(m_value >>= rhs.m_value)) ->
strong_type&
789 requires std::unsigned_integral<value_type>
791 m_value >>= rhs.m_value;
800 constexpr auto begin() const noexcept(noexcept(
std::ranges::
begin(m_value)))
803 return std::ranges::begin(m_value);
810 return std::ranges::begin(m_value);
814 constexpr auto end() const noexcept(noexcept(
std::ranges::
end(m_value)))
817 return std::ranges::end(m_value);
821 constexpr auto end() noexcept(noexcept(
std::ranges::
end(m_value)))
824 return std::ranges::end(m_value);
833 const strong_type& rhs)
noexcept(
noexcept(ostream << rhs.m_value)) -> std::ostream&
836 return ostream << rhs.m_value;
841 strong_type& rhs)
noexcept(
noexcept(istream >> rhs.m_value)) -> std::istream&
844 return istream >> rhs.m_value;
856template <
typename Tag,
typename T,
typename... Args>
857constexpr auto make_strong_type(Args&&... args)
noexcept(std::is_nothrow_constructible_v<T, Args...>)
858 requires std::constructible_from<std::remove_cvref_t<T>, Args...>
860 return strong_type<std::remove_cvref_t<T>, Tag>{std::forward<Args>(args)...};
864template <
typename Tag,
typename T,
typename U,
typename... Args>
866 std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
867 requires std::constructible_from<T, std::initializer_list<U>&, Args...>
869 return strong_type<std::remove_cvref_t<T>, Tag>{ilist, std::forward<Args>(args)...};
873template <
typename Tag,
typename T>
875 std::is_nothrow_constructible_v<strong_type<std::remove_cvref_t<T>, Tag>, T>)
876 requires std::constructible_from<std::remove_cvref_t<T>, T>
890template <::gw::hashable T, ::gw::complete Tag>
893 [[nodiscard]]
auto inline operator()(const ::gw::strong_type<T, Tag>& strong_type)
const noexcept ->
size_t {
894 auto tag_hash = hash<type_index>{}(type_index{
typeid(Tag)});
895 auto value_hash = hash<T>{}(strong_type.value());
896 return tag_hash ^ value_hash;
906template <
typename T,
typename Tag,
class CharT>
911 template <
class ParseContext>
912 constexpr auto parse(ParseContext& context) -> ParseContext::iterator {
913 return context.
begin();
918 template <
class FormatContext>
919 auto format(const ::gw::strong_type<T, Tag>& strong_type, FormatContext& context)
const -> FormatContext::iterator
920#if __cplusplus > 202002L
921 requires std::formattable<T, CharT>
924 if constexpr (::gw::named<Tag>) {
925 return format_to(context.out(),
"{}: {}", Tag::name(), strong_type.value());
928 return format_to(context.out(),
"{}", strong_type.value());
Strong type wrapper.
Definition strong_type.hpp:46
constexpr auto transform(F &&func) &noexcept(noexcept(func(m_value))) -> strong_type
returns a gw::strong_type containing the transformed contained value
Definition strong_type.hpp:127
constexpr auto operator%(const strong_type &rhs) &&noexcept(noexcept(m_value % rhs.m_value)) -> strong_type
calculates the remainder of the contained values
Definition strong_type.hpp:471
constexpr auto operator%(const strong_type &rhs) const &noexcept(noexcept(m_value % rhs.m_value)) -> strong_type
calculates the remainder of the contained values
Definition strong_type.hpp:457
constexpr auto operator+(const strong_type &rhs) const &noexcept(noexcept(m_value+rhs.m_value)) -> strong_type
adds the contained values
Definition strong_type.hpp:345
constexpr auto begin() const noexcept(noexcept(std::ranges::begin(m_value)))
returns an iterator to the beginning of the contained value
Definition strong_type.hpp:800
constexpr auto operator+(strong_type &&rhs) &&noexcept(noexcept(m_value+rhs.m_value)) -> strong_type
adds the contained values
Definition strong_type.hpp:366
constexpr auto operator/(strong_type &&rhs) const &noexcept(noexcept(m_value/rhs.m_value)) -> strong_type
devides the contained values
Definition strong_type.hpp:436
constexpr auto operator-() const &noexcept(noexcept(-m_value)) -> strong_type
negates the contained value
Definition strong_type.hpp:331
constexpr auto operator<<(const strong_type &rhs) const &noexcept(noexcept(m_value<< rhs.m_value)) -> strong_type
performs binary left shift on the contained values
Definition strong_type.hpp:660
constexpr auto operator>>(strong_type &&rhs) const &noexcept(noexcept(m_value > > rhs.m_value)) -> strong_type
performs binary right shift on the contained values
Definition strong_type.hpp:695
constexpr auto operator/(strong_type &&rhs) &&noexcept(noexcept(m_value/rhs.m_value)) -> strong_type
devides the contained values
Definition strong_type.hpp:450
constexpr strong_type(std::initializer_list< U > ilist, Args &&... args) noexcept(std::is_nothrow_constructible_v< value_type, std::initializer_list< U > &, Args... >)
constructs the gw::strong_type object
Definition strong_type.hpp:67
constexpr auto operator-(strong_type &&rhs) &&noexcept(noexcept(m_value - rhs.m_value)) -> strong_type
subtracts the contained values
Definition strong_type.hpp:394
constexpr auto operator^(strong_type &&rhs) &&noexcept(noexcept(m_value ^ rhs.m_value)) -> strong_type
performs binary XOR on the contained values
Definition strong_type.hpp:653
constexpr auto operator>>(strong_type &&rhs) &&noexcept(noexcept(m_value > > rhs.m_value)) -> strong_type
performs binary right shift on the contained values
Definition strong_type.hpp:709
constexpr auto operator<(const strong_type &rhs) const &noexcept(noexcept(m_value< rhs.m_value)) -> bool
compares gw::strong_type objects
Definition strong_type.hpp:197
constexpr auto value() &noexcept -> value_type &
returns the contained value
Definition strong_type.hpp:105
constexpr auto operator>>(const strong_type &rhs) const &noexcept(noexcept(m_value > > rhs.m_value)) -> strong_type
performs binary right shift on the contained values
Definition strong_type.hpp:688
constexpr auto end() const noexcept(noexcept(std::ranges::end(m_value)))
returns an iterator to the end of the contained value
Definition strong_type.hpp:814
constexpr auto operator-(const strong_type &rhs) &&noexcept(noexcept(m_value - rhs.m_value)) -> strong_type
subtracts the contained values
Definition strong_type.hpp:387
constexpr auto value() const &&noexcept -> const value_type &&
returns the contained value
Definition strong_type.hpp:108
constexpr auto operator^(strong_type &&rhs) const &noexcept(noexcept(m_value ^ rhs.m_value)) -> strong_type
performs binary XOR on the contained values
Definition strong_type.hpp:639
constexpr auto operator>>(const strong_type &rhs) &&noexcept(noexcept(m_value > > rhs.m_value)) -> strong_type
performs binary right shift on the contained values
Definition strong_type.hpp:702
constexpr auto operator->() noexcept -> value_type *
accesses the contained value
Definition strong_type.hpp:87
constexpr auto operator&(strong_type &&rhs) const &noexcept(noexcept(m_value &rhs.m_value)) -> strong_type
performs binary AND on the contained values
Definition strong_type.hpp:583
constexpr auto operator==(const strong_type &rhs) const &noexcept(noexcept(m_value==rhs.m_value)) -> bool
compares gw::strong_type objects
Definition strong_type.hpp:183
constexpr auto operator-() &&noexcept(noexcept(-m_value)) -> strong_type
negates the contained value
Definition strong_type.hpp:338
constexpr auto operator%(strong_type &&rhs) &&noexcept(noexcept(m_value % rhs.m_value)) -> strong_type
calculates the remainder of the contained values
Definition strong_type.hpp:478
constexpr auto operator>(const strong_type &rhs) const &noexcept(noexcept(m_value > rhs.m_value)) -> bool
compares gw::strong_type objects
Definition strong_type.hpp:204
constexpr auto operator-(const strong_type &rhs) const &noexcept(noexcept(m_value - rhs.m_value)) -> strong_type
subtracts the contained values
Definition strong_type.hpp:373
constexpr auto transform(F &&func) &&noexcept(noexcept(func(m_value))) -> strong_type
returns a gw::strong_type containing the transformed contained value
Definition strong_type.hpp:144
constexpr auto operator*(strong_type &&rhs) const &noexcept(noexcept(m_value *rhs.m_value)) -> strong_type
multiplies the contained values
Definition strong_type.hpp:408
constexpr auto operator&(const strong_type &rhs) const &noexcept(noexcept(m_value &rhs.m_value)) -> strong_type
performs binary AND on the contained values
Definition strong_type.hpp:576
constexpr auto operator--() &noexcept(noexcept(--m_value)) -> strong_type &
decrements the contained value
Definition strong_type.hpp:283
constexpr auto value() const &noexcept -> const value_type &
returns the contained value
Definition strong_type.hpp:102
constexpr auto operator++(int) &noexcept(noexcept(m_value++)) -> strong_type
increments the contained value
Definition strong_type.hpp:269
constexpr auto operator/(const strong_type &rhs) &&noexcept(noexcept(m_value/rhs.m_value)) -> strong_type
devides the contained values
Definition strong_type.hpp:443
constexpr auto operator^(const strong_type &rhs) &&noexcept(noexcept(m_value ^ rhs.m_value)) -> strong_type
performs binary XOR on the contained values
Definition strong_type.hpp:646
constexpr auto operator|(strong_type &&rhs) const &noexcept(noexcept(m_value|rhs.m_value)) -> strong_type
performs binary OR on the contained values
Definition strong_type.hpp:611
constexpr auto operator+() const &noexcept(noexcept(+m_value)) -> strong_type
affirms the contained value
Definition strong_type.hpp:317
constexpr auto operator<<(strong_type &&rhs) &&noexcept(noexcept(m_value<< rhs.m_value)) -> strong_type
performs binary left shift on the contained values
Definition strong_type.hpp:681
~strong_type() noexcept(std::is_nothrow_destructible_v< value_type >)=default
destroys the contained value
constexpr auto value() &&noexcept -> value_type &&
returns the contained value
Definition strong_type.hpp:111
constexpr auto operator<<(const strong_type &rhs) &&noexcept(noexcept(m_value<< rhs.m_value)) -> strong_type
performs binary left shift on the contained values
Definition strong_type.hpp:674
constexpr auto operator+(strong_type &&rhs) const &noexcept(noexcept(m_value+rhs.m_value)) -> strong_type
adds the contained values
Definition strong_type.hpp:352
constexpr auto operator|(const strong_type &rhs) const &noexcept(noexcept(m_value|rhs.m_value)) -> strong_type
performs binary OR on the contained values
Definition strong_type.hpp:604
constexpr auto operator*() &&noexcept -> value_type &&
accesses the contained value
Definition strong_type.hpp:99
constexpr auto operator*(const strong_type &rhs) &&noexcept(noexcept(m_value *rhs.m_value)) -> strong_type
multiplies the contained values
Definition strong_type.hpp:415
constexpr auto operator<<(strong_type &&rhs) const &noexcept(noexcept(m_value<< rhs.m_value)) -> strong_type
performs binary left shift on the contained values
Definition strong_type.hpp:667
constexpr auto operator++() &noexcept(noexcept(++m_value)) -> strong_type &
increments the contained value
Definition strong_type.hpp:253
constexpr auto operator&(strong_type &&rhs) &&noexcept(noexcept(m_value &rhs.m_value)) -> strong_type
performs binary AND on the contained values
Definition strong_type.hpp:597
constexpr auto operator|(const strong_type &rhs) &&noexcept(noexcept(m_value|rhs.m_value)) -> strong_type
performs binary OR on the contained values
Definition strong_type.hpp:618
constexpr auto operator*() const &noexcept -> const value_type &
accesses the contained value
Definition strong_type.hpp:90
Tag tag_type
The tag type.
Definition strong_type.hpp:53
T value_type
The type of the contained value.
Definition strong_type.hpp:52
constexpr strong_type(Args &&... args) noexcept(std::is_nothrow_constructible_v< value_type, Args... >)
Construct the gw::strong_type object.
Definition strong_type.hpp:61
constexpr auto operator/(const strong_type &rhs) const &noexcept(noexcept(m_value/rhs.m_value)) -> strong_type
devides the contained values
Definition strong_type.hpp:429
constexpr auto operator*(strong_type &&rhs) &&noexcept(noexcept(m_value *rhs.m_value)) -> strong_type
multiplies the contained values
Definition strong_type.hpp:422
constexpr auto operator|(strong_type &&rhs) &&noexcept(noexcept(m_value|rhs.m_value)) -> strong_type
performs binary OR on the contained values
Definition strong_type.hpp:625
constexpr auto operator&(const strong_type &rhs) &&noexcept(noexcept(m_value &rhs.m_value)) -> strong_type
performs binary AND on the contained values
Definition strong_type.hpp:590
constexpr auto begin() noexcept(noexcept(std::ranges::begin(m_value)))
returns an iterator to the beginning of the contained value
Definition strong_type.hpp:807
constexpr auto operator*() &noexcept -> value_type &
accesses the contained value
Definition strong_type.hpp:93
constexpr auto operator*(const strong_type &rhs) const &noexcept(noexcept(m_value *rhs.m_value)) -> strong_type
multiplies the contained values
Definition strong_type.hpp:401
friend auto operator<<(std::ostream &ostream, const strong_type &rhs) noexcept(noexcept(ostream<< rhs.m_value)) -> std::ostream &
inserts formatted data
Definition strong_type.hpp:832
friend auto operator>>(std::istream &istream, strong_type &rhs) noexcept(noexcept(istream > > rhs.m_value)) -> std::istream &
extracts formatted data
Definition strong_type.hpp:840
constexpr auto operator++(int) &&noexcept(noexcept(m_value++)) -> strong_type
increments the contained value
Definition strong_type.hpp:276
constexpr auto operator--() &&noexcept(noexcept(--m_value)) -> strong_type &&
decrements the contained value
Definition strong_type.hpp:291
constexpr auto emplace(Args &&... args) noexcept(std::is_nothrow_constructible_v< value_type, Args... >) -> value_type &
constructs the contained value in-place
Definition strong_type.hpp:171
constexpr auto operator--(int) &&noexcept(noexcept(m_value--)) -> strong_type
decrements the contained value
Definition strong_type.hpp:306
constexpr void reset() noexcept(std::is_nothrow_default_constructible_v< value_type >)
destroys any contained value
Definition strong_type.hpp:163
constexpr auto operator*() const &&noexcept -> const value_type &&
accesses the contained value
Definition strong_type.hpp:96
constexpr auto end() noexcept(noexcept(std::ranges::end(m_value)))
returns an iterator to the end of the contained value
Definition strong_type.hpp:821
constexpr auto transform(F &&func) const &noexcept(noexcept(func(m_value))) -> strong_type
returns a gw::strong_type containing the transformed contained value
Definition strong_type.hpp:119
constexpr void swap(strong_type &rhs) noexcept(std::is_nothrow_swappable_v< value_type >)
specializes the std::swap algorithm
Definition strong_type.hpp:155
constexpr auto operator+(const strong_type &rhs) &&noexcept(noexcept(m_value+rhs.m_value)) -> strong_type
adds the contained values
Definition strong_type.hpp:359
constexpr auto operator++() &&noexcept(noexcept(++m_value)) -> strong_type &&
increments the contained value
Definition strong_type.hpp:261
constexpr auto operator--(int) &noexcept(noexcept(m_value--)) -> strong_type
decrements the contained value
Definition strong_type.hpp:299
constexpr auto operator+() &&noexcept(noexcept(+m_value)) -> strong_type
affirms the contained value
Definition strong_type.hpp:324
constexpr auto operator~() const &noexcept(noexcept(~m_value)) -> strong_type
inverts the contained value
Definition strong_type.hpp:569
constexpr auto transform(F &&func) const &&noexcept(noexcept(func(m_value))) -> strong_type
returns a gw::strong_type containing the transformed contained value
Definition strong_type.hpp:135
constexpr auto operator^(const strong_type &rhs) const &noexcept(noexcept(m_value ^ rhs.m_value)) -> strong_type
performs binary XOR on the contained values
Definition strong_type.hpp:632
constexpr auto operator%(strong_type &&rhs) const &noexcept(noexcept(m_value % rhs.m_value)) -> strong_type
calculates the remainder of the contained values
Definition strong_type.hpp:464
constexpr auto operator-(strong_type &&rhs) const &noexcept(noexcept(m_value - rhs.m_value)) -> strong_type
subtracts the contained values
Definition strong_type.hpp:380
Concept for arithmetic types.
Definition concepts.hpp:18
Concept for decrementable types.
Definition concepts.hpp:29
Concept for incrementable types.
Definition concepts.hpp:22
Concept for istreamable types.
Definition concepts.hpp:52
Concept for ostreamable types.
Definition concepts.hpp:46
GW namespace.
Definition concepts.hpp:14
constexpr auto make_strong_type(Args &&... args) noexcept(std::is_nothrow_constructible_v< T, Args... >)
creates a gw::strong_type object
Definition strong_type.hpp:857