@@ -117,6 +117,11 @@ namespace kangaru {
117117 operator T const & () const ;
118118 #endif
119119
120+ #if KANGARU5_RVALUE_CONST_AMBIGUOUS()
121+ template <deducible T>
122+ operator T const && () const ;
123+ #endif
124+
120125 #if KANGARU5_RVALUE_AMBIGUOUS()
121126 template <typename T>
122127 operator T&& () const ;
@@ -127,20 +132,19 @@ namespace kangaru {
127132 using is_deducer = kangaru_deducer_tag;
128133
129134 template <deducible T>
130- operator T () const ;
135+ operator T ();
131136
132137 template <deducible T>
133- operator T& ();
138+ operator T& () const ;
134139
135- #if KANGARU5_LVALUE_CONST_AMBIGUOUS()
136140 template <deducible T>
137- operator T const & ();
138- #endif
141+ operator T const & () const ;
142+
143+ template <deducible T>
144+ operator T const && () const ;
139145
140- #if KANGARU5_RVALUE_AMBIGUOUS()
141146 template <typename T>
142- operator T&& ();
143- #endif
147+ operator T&& () const ;
144148 };
145149
146150 KANGARU5_EXPORT struct placeholder_deducer {
@@ -555,42 +559,118 @@ namespace kangaru {
555559 }
556560
557561 namespace detail ::deducer {
562+ template <typename T, typename F, typename , typename >
563+ inline constexpr auto callable_with_nth_parameter_being_expand = false ;
564+
558565 template <typename T, typename F, std::size_t ... before, std::size_t ... after>
559- inline consteval auto callable_with_nth_parameter_being_expand ( std::index_sequence<before...>, std::index_sequence<after...>) -> bool {
560- return callable<
566+ inline constexpr auto callable_with_nth_parameter_being_expand<T, F, std::index_sequence<before...>, std::index_sequence<after...>> =
567+ callable<
561568 F,
562569 detail::utility::expand<placeholder_deducer, before>...,
563570 T,
564571 detail::utility::expand<placeholder_deducer, after>...
565572 >;
566- }
567573
568574 template <typename T, typename F, std::size_t nth, std::size_t max>
569- inline constexpr auto callable_with_nth_parameter_being = bool {
570- KANGARU5_NO_ADL (callable_with_nth_parameter_being_expand<T, F>)(std::make_index_sequence<nth>{}, std::make_index_sequence<max - nth - 1 >{})
571- };
575+ concept callable_with_nth_parameter_being =
576+ callable_with_nth_parameter_being_expand<T, F, std::make_index_sequence<nth>, std::make_index_sequence<max - nth - 1 >>;
572577
573578 template <typename F, std::size_t nth, std::size_t max>
574- inline constexpr auto is_nth_parameter_prvalue = bool {
579+ concept function_nth_parameter_prvalue =
575580 not callable_with_nth_parameter_being<ambiguous_prvalue_deducer, F, nth, max>
576- and callable_with_nth_parameter_being<ambiguous_overloaded_reference_deducer, F, nth, max>
577- };
581+ and callable_with_nth_parameter_being<ambiguous_overloaded_reference_deducer, F, nth, max>;
582+
583+ template <typename T, typename F, std::size_t nth, std::size_t max>
584+ concept callable_with_lvalue_const_ref = callable_with_nth_parameter_being<
585+ filtered_value_category_deducer<T, reference_kind::lvalue_const_reference>,
586+ F,
587+ nth,
588+ max
589+ >;
590+
591+ // TODO: Remove conditionals, convert to pure boolean expressions
592+ template <typename T, typename F, std::size_t nth, std::size_t max>
593+ concept callable_with_rvalue_const_ref = (
594+ callable_with_lvalue_const_ref<T, F, nth, max>
595+ ? not callable_with_nth_parameter_being<
596+ filtered_value_category_deducer<T, reference_kind::lvalue_const_reference_and_rvalue_const_reference>,
597+ F,
598+ nth,
599+ max
600+ >
601+ : (
602+ callable_with_nth_parameter_being<
603+ filtered_value_category_deducer<T, reference_kind::rvalue_const_reference>,
604+ F,
605+ nth,
606+ max
607+ > or (
608+ callable_with_nth_parameter_being<
609+ filtered_value_category_deducer<T, reference_kind::rvalue_reference>,
610+ F,
611+ nth,
612+ max
613+ > and not callable_with_nth_parameter_being<
614+ filtered_value_category_deducer<T, reference_kind::rvalue_reference_and_rvalue_const_reference>,
615+ F,
616+ nth,
617+ max
618+ >
619+ )
620+ )
621+ );
622+
623+ template <typename T, typename F, std::size_t nth, std::size_t max>
624+ constexpr auto callable_with_lvalue_ref =
625+ callable_with_lvalue_const_ref<T, F, nth, max>
626+ ? not callable_with_nth_parameter_being<
627+ filtered_value_category_deducer<T, reference_kind::lvalue_reference_and_lvalue_const_reference>,
628+ F,
629+ nth,
630+ max
631+ >
632+ : callable_with_nth_parameter_being<
633+ filtered_value_category_deducer<T, reference_kind::lvalue_reference>,
634+ F,
635+ nth,
636+ max
637+ >;
638+
639+ template <typename T, typename F, std::size_t nth, std::size_t max>
640+ constexpr auto callable_with_rvalue_ref =
641+ callable_with_rvalue_const_ref<T, F, nth, max>
642+ ? not callable_with_nth_parameter_being<
643+ filtered_value_category_deducer<T, reference_kind::rvalue_reference_and_rvalue_const_reference>,
644+ F,
645+ nth,
646+ max
647+ >
648+ : callable_with_lvalue_const_ref<T, F, nth, max>
649+ ? not callable_with_nth_parameter_being<
650+ filtered_value_category_deducer<T, reference_kind::lvalue_const_reference_and_rvalue_reference>,
651+ F,
652+ nth,
653+ max
654+ >
655+ : callable_with_nth_parameter_being<
656+ filtered_value_category_deducer<T, reference_kind::rvalue_reference>,
657+ F,
658+ nth,
659+ max
660+ >;
578661
579662 template <typename T, typename F, std::size_t nth, std::size_t max>
580663 inline consteval auto reference_kind_for_nth_parameter () -> reference_kind {
581- if constexpr (is_nth_parameter_prvalue <F, nth, max>) {
664+ if constexpr (function_nth_parameter_prvalue <F, nth, max>) {
582665 return reference_kind::none;
583666 } else {
584667 // Welcome to insanity
585668
586669 // Only one kind of parameter will accept a lvalue const reference, and it's a lvalue const reference.
587670 // If the function is callable with a lvalue const reference, then it means there's an overload that accepts it.
588- constexpr auto callable_with_lvalue_const_ref = callable_with_nth_parameter_being<
589- filtered_value_category_deducer<T, reference_kind::lvalue_const_reference>,
590- F,
591- nth,
592- max
593- >;
671+ constexpr auto lvalue_const_ref = callable_with_lvalue_const_ref<T, F, nth, max>
672+ ? reference_kind::lvalue_const_reference
673+ : reference_kind::none;
594674
595675 // Now we have something harder to match. Sending a rvalue constant reference would indeed match a rvalue
596676 // constant reference parameter, but would also match a lvalue constant reference. This means that if we
@@ -604,82 +684,31 @@ namespace kangaru {
604684 // On the contrary, if there was no match for lvalue constant reference:
605685 // - We match for rvalue constant reference. If it matches, we're gold.
606686 // - If we don't match, we exclude matching with mutable rvalue for clang
607- constexpr auto callable_with_rvalue_const_ref = callable_with_lvalue_const_ref
608- ? not callable_with_nth_parameter_being<
609- filtered_value_category_deducer<T, reference_kind::lvalue_const_reference_and_rvalue_const_reference>,
610- F,
611- nth,
612- max
613- >
614- : (
615- callable_with_nth_parameter_being<
616- filtered_value_category_deducer<T, reference_kind::rvalue_const_reference>,
617- F,
618- nth,
619- max
620- > or (
621- callable_with_nth_parameter_being<
622- filtered_value_category_deducer<T, reference_kind::rvalue_reference>,
623- F,
624- nth,
625- max
626- > and not callable_with_nth_parameter_being<
627- filtered_value_category_deducer<T, reference_kind::rvalue_reference_and_rvalue_const_reference>,
628- F,
629- nth,
630- max
631- >
632- )
633- );
687+ constexpr auto rvalue_const_ref = callable_with_rvalue_const_ref<T, F, nth, max>
688+ ? reference_kind::rvalue_const_reference
689+ : reference_kind::none;
634690
635691 // To check for normal lvalue references, we need to first check if we already match with a const reference.
636692 // If we did match, then we'll do the trick where we try to call the function with a deducer that can
637693 // Deduce both kind. If the call is ambiguous, then we have a candidate in the overload set that take a lvalue ref.
638694 // Otherwise, we can just match with lvalue references.
639- constexpr auto callable_with_lvalue_ref = callable_with_lvalue_const_ref
640- ? not callable_with_nth_parameter_being<
641- filtered_value_category_deducer<T, reference_kind::lvalue_reference_and_lvalue_const_reference>,
642- F,
643- nth,
644- max
645- >
646- : callable_with_nth_parameter_being<
647- filtered_value_category_deducer<T, reference_kind::lvalue_reference>,
648- F,
649- nth,
650- max
651- >;
695+ constexpr auto lvalue_ref = callable_with_lvalue_ref<T, F, nth, max>
696+ ? reference_kind::lvalue_reference
697+ : reference_kind::none;
652698
653699 // Here we finally check for rvalue references. They can match rvalue references, rvalue const references, and
654700 // lvalue const references. We need take into account if we matched for them them before in order to do the right
655701 // little dance of ambiguous call check.
656- constexpr auto callable_with_rvalue_ref = callable_with_rvalue_const_ref
657- ? not callable_with_nth_parameter_being<
658- filtered_value_category_deducer<T, reference_kind::rvalue_reference_and_rvalue_const_reference>,
659- F,
660- nth,
661- max
662- >
663- : callable_with_lvalue_const_ref
664- ? not callable_with_nth_parameter_being<
665- filtered_value_category_deducer<T, reference_kind::lvalue_const_reference_and_rvalue_reference>,
666- F,
667- nth,
668- max
669- >
670- : callable_with_nth_parameter_being<
671- filtered_value_category_deducer<T, reference_kind::rvalue_reference>,
672- F,
673- nth,
674- max
675- >;
702+ constexpr auto rvalue_ref = callable_with_rvalue_ref<T, F, nth, max>
703+ ? reference_kind::rvalue_reference
704+ : reference_kind::none;
676705
677706 // We build the bitmask enum to express what overloads of different reference kind exists
678707 return (
679- (callable_with_lvalue_ref ? reference_kind::lvalue_reference : reference_kind::none)
680- | (callable_with_lvalue_const_ref ? reference_kind::lvalue_const_reference : reference_kind::none)
681- | (callable_with_rvalue_ref ? reference_kind::rvalue_reference : reference_kind::none)
682- | (callable_with_rvalue_const_ref ? reference_kind::rvalue_const_reference : reference_kind::none)
708+ lvalue_ref
709+ | lvalue_const_ref
710+ | rvalue_ref
711+ | rvalue_const_ref
683712 );
684713 }
685714 }
@@ -692,7 +721,7 @@ namespace kangaru {
692721
693722 template <typename F, typename Deducer, std::size_t nth, std::size_t arity>
694723 using prvalue_filtered_deducer_for = detail::type_traits::conditional_t <
695- not is_nth_parameter_prvalue <F, nth, arity>
724+ not function_nth_parameter_prvalue <F, nth, arity>
696725 and callable_with_nth_parameter_being<exclude_prvalue_deducer<Deducer>, F, nth, arity>,
697726 exclude_prvalue_deducer<Deducer>,
698727 exclude_references_deducer<Deducer>
0 commit comments