@@ -33,6 +33,21 @@ QT_BEGIN_NAMESPACE
3333
3434namespace QtPrivate {
3535
36+ template <typename Applier, size_t ...Is>
37+ void applyIndexSwitch (size_t index, Applier&& applier, std::index_sequence<Is...>)
38+ {
39+ // TODO: check if it's optimized properly on gcc.
40+ // A superficial research reveals that gcc may compile this code into a linear search,
41+ // whereas 'index' should be found in O(1) time like in a proper c++ switch.
42+ ((Is == index ? applier (std::integral_constant<size_t , Is>{}) : static_cast <void >(0 )), ...);
43+ }
44+
45+ template <size_t IndexCount, typename Applier>
46+ void applyIndexSwitch (size_t index, Applier&& applier)
47+ {
48+ applyIndexSwitch (index, std::forward<Applier>(applier), std::make_index_sequence<IndexCount>());
49+ }
50+
3651// TODO: move to a separate header in Qt 6.11
3752template <typename Interface>
3853class QQuasiVirtualInterface
@@ -166,11 +181,10 @@ class QQuasiVirtualSubclass : public Interface
166181 static_assert (methodIndexMask == (uint64_t (1 ) << sizeof ...(Is)) - 1 ,
167182 " Mapping between base and overridden methods is not unique" );
168183
169- // TODO: check if it's optimized properly on gcc
170- ((interfaceMethodIndex<Is>() == index
171- ? std::tuple_element_t <Is, Methods<>>::doInvoke (subclass, ret, args)
172- : static_cast <void >(0 ))
173- , ...);
184+ auto doInvoke = [&](auto idxConstant) {
185+ std::tuple_element_t <idxConstant.value , Methods<>>::doInvoke (subclass, ret, args);
186+ };
187+ applyIndexSwitch (index, doInvoke, std::index_sequence<interfaceMethodIndex<Is>()...>{});
174188 }
175189
176190 static void callImpl (size_t index, typename Interface::base_interface &intf, void *ret, void *args)
@@ -810,25 +824,18 @@ class QRangeModelImplBase : public QtPrivate::QQuasiVirtualInterface<QRangeModel
810824protected:
811825 // Helpers for calling a lambda with the element of a statically
812826 // sized range (tuple or array) with a runtime index.
813- template <typename Tuple, typename F, std::size_t ...Is>
814- static void call_at (Tuple &&tuple, std::size_t idx, std::index_sequence<Is...>, F &&function)
815- {
816- static_assert (QRangeModelDetails::tuple_like_v<q20::remove_cvref_t <Tuple>>);
817- if (QRangeModelDetails::isValid (tuple))
818- ((Is == idx ? static_cast <void >(function (get<Is>(
819- QRangeModelDetails::refTo (std::forward<Tuple>(tuple)))))
820- : static_cast <void >(0 )), ...);
821- }
822-
823827 template <typename T, typename F,
824828 std::enable_if_t <QRangeModelDetails::tuple_like_v<q20::remove_cvref_t <T>>, bool > = true >
825829 static auto for_element_at (T &&tuple, std::size_t idx, F &&function)
826830 {
827831 using type = QRangeModelDetails::wrapped_t <T>;
828832 constexpr size_t size = std::tuple_size_v<type>;
829833 Q_ASSERT (idx < size);
830- return call_at (std::forward<T>(tuple), idx, std::make_index_sequence<size>{},
831- std::forward<F>(function));
834+ if (QRangeModelDetails::isValid (tuple)) {
835+ QtPrivate::applyIndexSwitch<size>(idx, [&](auto idxConstant) {
836+ function (get<idxConstant.value >(QRangeModelDetails::refTo (std::forward<T>(tuple))));
837+ });
838+ }
832839 }
833840
834841 template <typename Array, typename F,
0 commit comments