diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index 71fb2ad35d0..0413c816fa4 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -1005,7 +1005,8 @@ inline void sort(Container &container, Predicate p) std::stable_sort(std::begin(container), std::end(container), p); } -template +// const lvalue +template inline Container sorted(const Container &container) { Container c = container; @@ -1013,20 +1014,34 @@ inline Container sorted(const Container &container) return c; } -template +// non-const lvalue +// This is needed because otherwise the "universal" reference below is used, modifying the input +// container. +template +inline Container sorted(Container &container) +{ + Container c = container; + sort(c); + return c; +} + +// non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) +template inline Container sorted(Container &&container) { sort(container); - return container; + return std::move(container); } -template +// const rvalue +template inline Container sorted(const Container &&container) { return sorted(container); } -template +// const lvalue +template inline Container sorted(const Container &container, Predicate p) { Container c = container; @@ -1034,21 +1049,34 @@ inline Container sorted(const Container &container, Predicate p) return c; } -template +// non-const lvalue +// This is needed because otherwise the "universal" reference below is used, modifying the input +// container. +template +inline Container sorted(Container &container, Predicate p) +{ + Container c = container; + sort(c, p); + return c; +} + +// non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) +template inline Container sorted(Container &&container, Predicate p) { sort(container, p); - return container; + return std::move(container); } -template +// const rvalue +template inline Container sorted(const Container &&container, Predicate p) { return sorted(container, p); } // pointer to member -template +template inline void sort(Container &container, R S::*member) { auto f = std::mem_fn(member); @@ -1059,7 +1087,8 @@ inline void sort(Container &container, R S::*member) }); } -template +// const lvalue +template inline Container sorted(const Container &container, R S::*member) { Container c = container; @@ -1067,21 +1096,34 @@ inline Container sorted(const Container &container, R S::*member) return c; } -template +// non-const lvalue +// This is needed because otherwise the "universal" reference below is used, modifying the input +// container. +template +inline Container sorted(Container &container, R S::*member) +{ + Container c = container; + sort(c, member); + return c; +} + +// non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) +template inline Container sorted(Container &&container, R S::*member) { sort(container, member); - return container; + return std::move(container); } -template +// const rvalue +template inline Container sorted(const Container &&container, R S::*member) { return sorted(container, member); } // pointer to member function -template +template inline void sort(Container &container, R (S::*function)() const) { auto f = std::mem_fn(function); @@ -1092,7 +1134,8 @@ inline void sort(Container &container, R (S::*function)() const) }); } -template +// const lvalue +template inline Container sorted(const Container &container, R (S::*function)() const) { Container c = container; @@ -1100,14 +1143,27 @@ inline Container sorted(const Container &container, R (S::*function)() const) return c; } -template +// non-const lvalue +// This is needed because otherwise the "universal" reference below is used, modifying the input +// container. +template +inline Container sorted(Container &container, R (S::*function)() const) +{ + Container c = container; + sort(c, function); + return c; +} + +// non-const rvalue (actually rvalue or lvalue, but lvalue is handled above) +template inline Container sorted(Container &&container, R (S::*function)() const) { sort(container, function); - return container; + return std::move(container); } -template +// const rvalue +template inline Container sorted(const Container &&container, R (S::*function)() const) { return sorted(container, function); diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp index 5f2eaf23e2f..dbe3d732a47 100644 --- a/tests/auto/algorithm/tst_algorithm.cpp +++ b/tests/auto/algorithm/tst_algorithm.cpp @@ -28,6 +28,7 @@ private slots: void findOrDefault(); void toReferences(); void take(); + void sorted(); }; @@ -550,6 +551,106 @@ void tst_Algorithm::take() } } +void tst_Algorithm::sorted() +{ + const QList vOrig{4, 3, 6, 5, 8}; + const QList vExpected{3, 4, 5, 6, 8}; + + // plain + { + // non-const lvalue + QList vncl = vOrig; + const QList rncl = Utils::sorted(vncl); + QCOMPARE(rncl, vExpected); + QCOMPARE(vncl, vOrig); // was not modified + + // const lvalue + const QList rcl = Utils::sorted(vOrig); + QCOMPARE(rcl, vExpected); + + // non-const rvalue + const auto vncr = [vOrig]() -> QList { return vOrig; }; + const QList rncr = Utils::sorted(vncr()); + QCOMPARE(rncr, vExpected); + + // const rvalue + const auto vcr = [vOrig]() -> const QList { return vOrig; }; + const QList rcr = Utils::sorted(vcr()); + QCOMPARE(rcr, vExpected); + } + + // predicate + { + // non-const lvalue + QList vncl = vOrig; + const QList rncl = Utils::sorted(vncl, [](int a, int b) { return a < b; }); + QCOMPARE(rncl, vExpected); + QCOMPARE(vncl, vOrig); // was not modified + + // const lvalue + const QList rcl = Utils::sorted(vOrig, [](int a, int b) { return a < b; }); + QCOMPARE(rcl, vExpected); + + // non-const rvalue + const auto vncr = [vOrig]() -> QList { return vOrig; }; + const QList rncr = Utils::sorted(vncr(), [](int a, int b) { return a < b; }); + QCOMPARE(rncr, vExpected); + + // const rvalue + const auto vcr = [vOrig]() -> const QList { return vOrig; }; + const QList rcr = Utils::sorted(vcr(), [](int a, int b) { return a < b; }); + QCOMPARE(rcr, vExpected); + } + + const QList mvOrig({4, 3, 2, 1}); + const QList mvExpected({1, 2, 3, 4}); + // member + { + // non-const lvalue + QList mvncl = mvOrig; + const QList rncl = Utils::sorted(mvncl, &Struct::member); + QCOMPARE(rncl, mvExpected); + QCOMPARE(mvncl, mvOrig); // was not modified + + // const lvalue + const QList rcl = Utils::sorted(mvOrig, &Struct::member); + QCOMPARE(rcl, mvExpected); + + // non-const rvalue + const auto vncr = [mvOrig]() -> QList { return mvOrig; }; + const QList rncr = Utils::sorted(vncr(), &Struct::member); + QCOMPARE(rncr, mvExpected); + + // const rvalue + const auto vcr = [mvOrig]() -> const QList { return mvOrig; }; + const QList rcr = Utils::sorted(vcr(), &Struct::member); + QCOMPARE(rcr, mvExpected); + } + + // member function + { + // non-const lvalue + QList mvncl = mvOrig; + const QList rncl = Utils::sorted(mvncl, &Struct::getMember); + QCOMPARE(rncl, mvExpected); + QCOMPARE(mvncl, mvOrig); // was not modified + + // const lvalue + const QList rcl = Utils::sorted(mvOrig, &Struct::getMember); + QCOMPARE(rcl, mvExpected); + + // non-const rvalue + const auto vncr = [mvOrig]() -> QList { return mvOrig; }; + const QList rncr = Utils::sorted(vncr(), &Struct::getMember); + QCOMPARE(rncr, mvExpected); + + // const rvalue + const auto vcr = [mvOrig]() -> const QList { return mvOrig; }; + const QList rcr = Utils::sorted(vcr(), &Struct::getMember); + QCOMPARE(rcr, mvExpected); + } +} + QTEST_GUILESS_MAIN(tst_Algorithm) #include "tst_algorithm.moc"