Skip to content

Commit 06ae338

Browse files
cjdbdanakj
andauthored
makes most operators hidden friends (#471)
This ensures that they're not placed in their function names' respective overload sets, which has a considerable impact on build times and on compiler diagnostics (as they're not listed as failed candidates when overload resolution fails). --------- Co-authored-by: Dana Jansens <[email protected]>
1 parent dbfdd7c commit 06ae338

32 files changed

+768
-1027
lines changed

sus/boxed/box.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,9 @@ class [[_sus_trivial_abi]] Box final : public __private::BoxBase<Box<T>, T> {
656656
return {};
657657
}
658658

659+
// Stream support.
660+
_sus_format_to_stream(Box);
661+
659662
private:
660663
enum FromPointer { FROM_POINTER };
661664
constexpr explicit Box(FromPointer, T* t) noexcept : t_(t) {}
@@ -708,9 +711,6 @@ struct fmt::formatter<::sus::boxed::Box<T>, Char> {
708711
::sus::string::__private::AnyFormatter<T, Char> underlying_;
709712
};
710713

711-
// Stream support.
712-
_sus_format_to_stream(sus::boxed, Box, T);
713-
714714
// Promote `Box` into the `sus` namespace.
715715
namespace sus {
716716
using ::sus::boxed::Box;

sus/choice/choice.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,9 @@ class Choice<__private::TypeList<Ts...>, Tags...> final {
911911
const Choice<__private::TypeList<RhsTs...>, RhsTag, RhsTags...>& r) =
912912
delete;
913913

914+
// Stream support.
915+
_sus_format_to_stream(Choice);
916+
914917
private:
915918
constexpr explicit Choice(IndexType i) noexcept : index_(i) {}
916919

@@ -1002,18 +1005,6 @@ struct fmt::formatter<
10021005
}
10031006
};
10041007

1005-
// Stream support (written out manually due to use of template specialization).
1006-
namespace sus::choice_type {
1007-
template <class... Ts, auto... Tags,
1008-
::sus::string::__private::StreamCanReceiveString<char> StreamType>
1009-
inline StreamType& operator<<(
1010-
StreamType& stream,
1011-
const Choice<__private::TypeList<Ts...>, Tags...>& value) {
1012-
return ::sus::string::__private::format_to_stream(stream,
1013-
fmt::to_string(value));
1014-
}
1015-
} // namespace sus::choice_type
1016-
10171008
// Promote Choice into the `sus` namespace.
10181009
namespace sus {
10191010
using ::sus::choice_type::Choice;

sus/collections/array.h

Lines changed: 130 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ struct Storage final {
6161
template <class T>
6262
struct Storage<T, 0> final {};
6363

64+
template <size_t I>
65+
constexpr bool array_cmp_impl(sus::cmp::Ordering auto& val, const auto& l,
66+
const auto& r) noexcept {
67+
auto cmp = l.get_unchecked(::sus::marker::unsafe_fn, I) <=>
68+
r.get_unchecked(::sus::marker::unsafe_fn, I);
69+
// Allow downgrading from equal to equivalent, but not the inverse.
70+
if (cmp != 0) val = cmp;
71+
// Short circuit by returning true when we find a difference.
72+
return val == 0;
73+
}
74+
75+
template <size_t... Is>
76+
constexpr auto array_cmp(sus::cmp::Ordering auto equal, const auto& l,
77+
const auto& r, std::index_sequence<Is...>) noexcept {
78+
auto val = equal;
79+
(true && ... && (array_cmp_impl<Is>(val, l, r)));
80+
return val;
81+
}
6482
} // namespace __private
6583

6684
/// A collection of objects of type `T`, with a fixed size `N`.
@@ -335,10 +353,11 @@ class Array final {
335353
/// Satisfies the [`Eq<Array<T, N>, Array<U, N>>`]($sus::cmp::Eq) concept.
336354
template <class U>
337355
requires(::sus::cmp::Eq<T, U>)
338-
constexpr bool operator==(const Array<U, N>& r) const& noexcept
356+
friend constexpr bool operator==(const Array& l,
357+
const Array<U, N>& r) noexcept
339358
requires(::sus::cmp::Eq<T>)
340359
{
341-
return eq_impl(r, std::make_index_sequence<N>());
360+
return l.eq_impl(r, std::make_index_sequence<N>());
342361
}
343362

344363
/// Satisfies the [`Eq<Array<T, N>, Slice<U>>`]($sus::cmp::Eq) concept.
@@ -405,6 +424,115 @@ class Array final {
405424
sus::iter::IterRefCounter::empty_for_view(), storage_.data_, N);
406425
}
407426

427+
/// Compares two Arrays.
428+
///
429+
/// Satisfies sus::cmp::StrongOrd<Array<T, N>> if sus::cmp::StrongOrd<T>.
430+
///
431+
/// Satisfies sus::cmp::Ord<Array<T, N>> if sus::cmp::Ord<T>.
432+
///
433+
/// Satisfies sus::cmp::PartialOrd<Array<T, N>> if sus::cmp::PartialOrd<T>.
434+
/// #[doc.overloads=array.cmp.array]
435+
template <class U>
436+
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
437+
friend constexpr std::strong_ordering operator<=>(
438+
const Array& l, const Array<U, N>& r) noexcept {
439+
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
440+
std::make_index_sequence<N>());
441+
}
442+
/// #[doc.overloads=array.cmp.array]
443+
template <class U>
444+
requires(::sus::cmp::ExclusiveOrd<T, U>)
445+
friend constexpr std::weak_ordering operator<=>(
446+
const Array& l, const Array<U, N>& r) noexcept {
447+
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
448+
std::make_index_sequence<N>());
449+
}
450+
/// #[doc.overloads=array.cmp.array]
451+
template <class U>
452+
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
453+
friend constexpr std::partial_ordering operator<=>(
454+
const Array& l, const Array<U, N>& r) noexcept {
455+
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
456+
std::make_index_sequence<N>());
457+
}
458+
459+
/// Compares an Array and a Slice.
460+
///
461+
/// Satisfies sus::cmp::StrongOrd<Array<T, N>, Slice<T>> if
462+
/// sus::cmp::StrongOrd<T>.
463+
///
464+
/// Satisfies sus::cmp::Ord<Array<T, N>, Slice<T>> if sus::cmp::Ord<T>.
465+
///
466+
/// Satisfies sus::cmp::PartialOrd<Array<T, N>, Slice<T>> if
467+
/// sus::cmp::PartialOrd<T>.
468+
/// #[doc.overloads=array.cmp.slice]
469+
template <class U>
470+
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
471+
friend constexpr std::strong_ordering operator<=>(
472+
const Array& l, const Slice<U>& r) noexcept {
473+
if (r.len() != N) return r.len() <=> N;
474+
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
475+
std::make_index_sequence<N>());
476+
}
477+
/// #[doc.overloads=array.cmp.slice]
478+
template <class U>
479+
requires(::sus::cmp::ExclusiveOrd<T, U>)
480+
friend constexpr std::weak_ordering operator<=>(const Array& l,
481+
const Slice<U>& r) noexcept {
482+
if (r.len() != N) return r.len() <=> N;
483+
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
484+
std::make_index_sequence<N>());
485+
}
486+
/// #[doc.overloads=array.cmp.slice]
487+
template <class U>
488+
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
489+
friend constexpr std::partial_ordering operator<=>(
490+
const Array& l, const Slice<U>& r) noexcept {
491+
if (r.len() != N) return r.len() <=> N;
492+
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
493+
std::make_index_sequence<N>());
494+
}
495+
496+
/// Compares an Array and a SliceMut.
497+
///
498+
/// Satisfies sus::cmp::StrongOrd<Array<T, N>, SliceMut<T>> if
499+
/// sus::cmp::StrongOrd<T>.
500+
///
501+
/// Satisfies sus::cmp::Ord<Array<T, N>, SliceMut<T>> if sus::cmp::Ord<T>.
502+
///
503+
/// Satisfies sus::cmp::PartialOrd<Array<T, N>, SliceMut<T>> if
504+
/// sus::cmp::PartialOrd<T>.
505+
/// #[doc.overloads=array.cmp.slicemut]
506+
template <class U>
507+
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
508+
friend constexpr std::strong_ordering operator<=>(
509+
const Array& l, const SliceMut<U>& r) noexcept {
510+
if (r.len() != N) return r.len() <=> N;
511+
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
512+
std::make_index_sequence<N>());
513+
}
514+
/// #[doc.overloads=array.cmp.slicemut]
515+
template <class U>
516+
requires(::sus::cmp::ExclusiveOrd<T, U>)
517+
friend constexpr std::weak_ordering operator<=>(
518+
const Array& l, const SliceMut<U>& r) noexcept {
519+
if (r.len() != N) return r.len() <=> N;
520+
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
521+
std::make_index_sequence<N>());
522+
}
523+
/// #[doc.overloads=array.cmp.slicemut]
524+
template <class U>
525+
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
526+
friend constexpr std::partial_ordering operator<=>(
527+
const Array& l, const SliceMut<U>& r) noexcept {
528+
if (r.len() != N) return r.len() <=> N;
529+
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
530+
std::make_index_sequence<N>());
531+
}
532+
533+
// Stream support.
534+
_sus_format_to_stream(Array);
535+
408536
private:
409537
enum WithDefault { WITH_DEFAULT };
410538
template <size_t... Is>
@@ -467,136 +595,6 @@ template <class T, class... Ts>
467595
std::same_as<std::remove_cvref_t<T>, std::remove_cvref_t<Ts>>))
468596
Array(T&&, Ts&&...) -> Array<std::remove_cvref_t<T>, 1u + sizeof...(Ts)>;
469597

470-
namespace __private {
471-
472-
template <size_t I>
473-
constexpr inline bool array_cmp_impl(sus::cmp::Ordering auto& val,
474-
const auto& l, const auto& r) noexcept {
475-
auto cmp = l.get_unchecked(::sus::marker::unsafe_fn, I) <=>
476-
r.get_unchecked(::sus::marker::unsafe_fn, I);
477-
// Allow downgrading from equal to equivalent, but not the inverse.
478-
if (cmp != 0) val = cmp;
479-
// Short circuit by returning true when we find a difference.
480-
return val == 0;
481-
};
482-
483-
template <size_t... Is>
484-
constexpr inline auto array_cmp(sus::cmp::Ordering auto equal, const auto& l,
485-
const auto& r,
486-
std::index_sequence<Is...>) noexcept {
487-
auto val = equal;
488-
(true && ... && (array_cmp_impl<Is>(val, l, r)));
489-
return val;
490-
};
491-
492-
} // namespace __private
493-
494-
/// Compares two Arrays.
495-
///
496-
/// Satisfies sus::cmp::StrongOrd<Array<T, N>> if sus::cmp::StrongOrd<T>.
497-
///
498-
/// Satisfies sus::cmp::Ord<Array<T, N>> if sus::cmp::Ord<T>.
499-
///
500-
/// Satisfies sus::cmp::PartialOrd<Array<T, N>> if sus::cmp::PartialOrd<T>.
501-
/// #[doc.overloads=array.cmp.array]
502-
template <class T, class U, size_t N>
503-
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
504-
constexpr inline std::strong_ordering operator<=>(
505-
const Array<T, N>& l, const Array<U, N>& r) noexcept {
506-
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
507-
std::make_index_sequence<N>());
508-
}
509-
/// #[doc.overloads=array.cmp.array]
510-
template <class T, class U, size_t N>
511-
requires(::sus::cmp::ExclusiveOrd<T, U>)
512-
constexpr inline std::weak_ordering operator<=>(const Array<T, N>& l,
513-
const Array<U, N>& r) noexcept {
514-
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
515-
std::make_index_sequence<N>());
516-
}
517-
/// #[doc.overloads=array.cmp.array]
518-
template <class T, class U, size_t N>
519-
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
520-
constexpr inline std::partial_ordering operator<=>(
521-
const Array<T, N>& l, const Array<U, N>& r) noexcept {
522-
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
523-
std::make_index_sequence<N>());
524-
}
525-
526-
/// Compares an Array and a Slice.
527-
///
528-
/// Satisfies sus::cmp::StrongOrd<Array<T, N>, Slice<T>> if
529-
/// sus::cmp::StrongOrd<T>.
530-
///
531-
/// Satisfies sus::cmp::Ord<Array<T, N>, Slice<T>> if sus::cmp::Ord<T>.
532-
///
533-
/// Satisfies sus::cmp::PartialOrd<Array<T, N>, Slice<T>> if
534-
/// sus::cmp::PartialOrd<T>.
535-
/// #[doc.overloads=array.cmp.slice]
536-
template <class T, class U, size_t N>
537-
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
538-
constexpr inline std::strong_ordering operator<=>(const Array<T, N>& l,
539-
const Slice<U>& r) noexcept {
540-
if (r.len() != N) return r.len() <=> N;
541-
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
542-
std::make_index_sequence<N>());
543-
}
544-
/// #[doc.overloads=array.cmp.slice]
545-
template <class T, class U, size_t N>
546-
requires(::sus::cmp::ExclusiveOrd<T, U>)
547-
constexpr inline std::weak_ordering operator<=>(const Array<T, N>& l,
548-
const Slice<U>& r) noexcept {
549-
if (r.len() != N) return r.len() <=> N;
550-
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
551-
std::make_index_sequence<N>());
552-
}
553-
/// #[doc.overloads=array.cmp.slice]
554-
template <class T, class U, size_t N>
555-
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
556-
constexpr inline std::partial_ordering operator<=>(const Array<T, N>& l,
557-
const Slice<U>& r) noexcept {
558-
if (r.len() != N) return r.len() <=> N;
559-
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
560-
std::make_index_sequence<N>());
561-
}
562-
563-
/// Compares an Array and a SliceMut.
564-
///
565-
/// Satisfies sus::cmp::StrongOrd<Array<T, N>, SliceMut<T>> if
566-
/// sus::cmp::StrongOrd<T>.
567-
///
568-
/// Satisfies sus::cmp::Ord<Array<T, N>, SliceMut<T>> if sus::cmp::Ord<T>.
569-
///
570-
/// Satisfies sus::cmp::PartialOrd<Array<T, N>, SliceMut<T>> if
571-
/// sus::cmp::PartialOrd<T>.
572-
/// #[doc.overloads=array.cmp.slicemut]
573-
template <class T, class U, size_t N>
574-
requires(::sus::cmp::ExclusiveStrongOrd<T, U>)
575-
constexpr inline std::strong_ordering operator<=>(
576-
const Array<T, N>& l, const SliceMut<U>& r) noexcept {
577-
if (r.len() != N) return r.len() <=> N;
578-
return __private::array_cmp(std::strong_ordering::equivalent, l, r,
579-
std::make_index_sequence<N>());
580-
}
581-
/// #[doc.overloads=array.cmp.slicemut]
582-
template <class T, class U, size_t N>
583-
requires(::sus::cmp::ExclusiveOrd<T, U>)
584-
constexpr inline std::weak_ordering operator<=>(const Array<T, N>& l,
585-
const SliceMut<U>& r) noexcept {
586-
if (r.len() != N) return r.len() <=> N;
587-
return __private::array_cmp(std::weak_ordering::equivalent, l, r,
588-
std::make_index_sequence<N>());
589-
}
590-
/// #[doc.overloads=array.cmp.slicemut]
591-
template <class T, class U, size_t N>
592-
requires(::sus::cmp::ExclusivePartialOrd<T, U>)
593-
constexpr inline std::partial_ordering operator<=>(
594-
const Array<T, N>& l, const SliceMut<U>& r) noexcept {
595-
if (r.len() != N) return r.len() <=> N;
596-
return __private::array_cmp(std::partial_ordering::equivalent, l, r,
597-
std::make_index_sequence<N>());
598-
}
599-
600598
/// Support for using structured bindings with `Array`.
601599
/// #[doc.overloads=array.structured.bindings]
602600
template <size_t I, class T, size_t N>
@@ -664,17 +662,6 @@ struct fmt::formatter<::sus::collections::Array<T, N>, Char> {
664662
::sus::string::__private::AnyFormatter<T, Char> underlying_;
665663
};
666664

667-
// Stream support (written out manually due to size_t template param).
668-
namespace sus::collections {
669-
template <class T, size_t N,
670-
::sus::string::__private::StreamCanReceiveString<char> StreamType>
671-
inline StreamType& operator<<(StreamType& stream, const Array<T, N>& value) {
672-
return ::sus::string::__private::format_to_stream(stream,
673-
fmt::to_string(value));
674-
}
675-
676-
} // namespace sus::collections
677-
678665
namespace sus::collections {
679666
// Documented in vec.h
680667
using ::sus::iter::begin;

sus/collections/slice.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ class [[_sus_trivial_abi]] Slice final {
248248
iter_refs_ = ::sus::iter::IterRefCounter::empty_for_view();
249249
}
250250

251+
// Stream support.
252+
_sus_format_to_stream(Slice);
253+
251254
#define _ptr_expr data_
252255
#define _len_expr len_
253256
#define _iter_refs_expr iter_refs_.to_iter_from_view()
@@ -471,6 +474,9 @@ class [[_sus_trivial_abi]] SliceMut final {
471474
slice_.iter_refs_ = ::sus::iter::IterRefCounter::empty_for_view();
472475
}
473476

477+
// Stream support.
478+
_sus_format_to_stream(SliceMut);
479+
474480
#define _ptr_expr slice_.data_
475481
#define _len_expr slice_.len_
476482
#define _iter_refs_expr slice_.iter_refs_.to_iter_from_view()
@@ -540,9 +546,6 @@ struct fmt::formatter<::sus::collections::Slice<T>, Char> {
540546
::sus::string::__private::AnyFormatter<T, Char> underlying_;
541547
};
542548

543-
// Stream support.
544-
_sus_format_to_stream(sus::collections, Slice, T);
545-
546549
// fmt support.
547550
template <class T, class Char>
548551
struct fmt::formatter<::sus::collections::SliceMut<T>, Char> {
@@ -568,9 +571,6 @@ struct fmt::formatter<::sus::collections::SliceMut<T>, Char> {
568571
::sus::string::__private::AnyFormatter<T, Char> underlying_;
569572
};
570573

571-
// Stream support.
572-
_sus_format_to_stream(sus::collections, SliceMut, T);
573-
574574
// Promote Slice into the `sus` namespace.
575575
namespace sus {
576576
using ::sus::collections::Slice;

0 commit comments

Comments
 (0)