diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index 7c0b73d2028..7c6fad0d9a3 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -332,7 +332,21 @@ inserter(QSet &container) // different container types for input and output, e.g. transforming a QList into a QSet -// function: +// function without result type deduction: +template class SC, // input container type + typename F, // function type + typename... SCArgs> // Arguments to SC +Q_REQUIRED_RESULT +decltype(auto) transform(const SC &container, F function) +{ + ResultContainer result; + result.reserve(container.size()); + std::transform(std::begin(container), std::end(container), inserter(result), function); + return result; +} + +// function with result type deduction: template class C, // result container type template class SC, // input container type typename F, // function type @@ -342,10 +356,7 @@ template class C, // result container type Q_REQUIRED_RESULT decltype(auto) transform(const SC &container, F function) { - ResultContainer result; - result.reserve(container.size()); - std::transform(std::begin(container), std::end(container), inserter(result), function); - return result; + return transform(container, function); } template class C, // result container type @@ -358,13 +369,10 @@ template class C, // result container type Q_REQUIRED_RESULT decltype(auto) transform(const SC &container, F function) { - ResultContainer result; - result.reserve(container.size()); - std::transform(std::begin(container), std::end(container), inserter(result), function); - return result; + return transform(container, function); } -// member function: +// member function without result type deduction: template class C, // result container type template class SC, // input container type typename R, @@ -376,7 +384,31 @@ decltype(auto) transform(const SC &container, R (S::*p)() const) return transform(container, std::mem_fn(p)); } -// members: +// member function with result type deduction: +template class SC, // input container type + typename R, + typename S, + typename... SCArgs> // Arguments to SC +Q_REQUIRED_RESULT +decltype(auto) transform(const SC &container, R (S::*p)() const) +{ + return transform(container, std::mem_fn(p)); +} + +// member without result type deduction: +template class SC, // input container + typename R, + typename S, + typename... SCArgs> // Arguments to SC +Q_REQUIRED_RESULT +decltype(auto) transform(const SC &container, R S::*p) +{ + return transform(container, std::mem_fn(p)); +} + +// member with result type deduction: template class C, // result container template class SC, // input container typename R, diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp index ab0a9177cc0..83b8505bfba 100644 --- a/tests/auto/algorithm/tst_algorithm.cpp +++ b/tests/auto/algorithm/tst_algorithm.cpp @@ -55,16 +55,23 @@ int stringToInt(const QString &s) } namespace { -struct Struct + +struct BaseStruct { - Struct(int m) : member(m) {} - bool operator==(const Struct &other) const { return member == other.member; } + BaseStruct(int m) : member(m) {} + bool operator==(const BaseStruct &other) const { return member == other.member; } + + int member; +}; + +struct Struct : public BaseStruct +{ + Struct(int m) : BaseStruct(m) {} bool isOdd() const { return member % 2 == 1; } bool isEven() const { return !isOdd(); } int getMember() const { return member; } - int member; }; } @@ -248,6 +255,57 @@ void tst_Algorithm::transform() Utils::sort(trans); QCOMPARE(trans, QList({1.5, 7.5, 17.5})); } + { + // specific result container with one template parameter (QVector) + std::vector v({1, 2, 3, 4}); + const QVector trans = Utils::transform>(v, [](int i) { + return new Struct(i); + }); + QCOMPARE(trans.size(), 4); + QCOMPARE(trans.at(0)->member, 1); + QCOMPARE(trans.at(1)->member, 2); + QCOMPARE(trans.at(2)->member, 3); + QCOMPARE(trans.at(3)->member, 4); + qDeleteAll(trans); + } + { + // specific result container with one of two template parameters (std::vector) + std::vector v({1, 2, 3, 4}); + const std::vector trans + = Utils::transform>(v, [](int i) { return new Struct(i); }); + QCOMPARE(trans.size(), 4ul); + QCOMPARE(trans.at(0)->member, 1); + QCOMPARE(trans.at(1)->member, 2); + QCOMPARE(trans.at(2)->member, 3); + QCOMPARE(trans.at(3)->member, 4); + qDeleteAll(trans); + } + { + // specific result container with two template parameters (std::vector) + std::vector v({1, 2, 3, 4}); + const std::vector> trans + = Utils::transform>>(v, [](int i) { + return new Struct(i); + }); + QCOMPARE(trans.size(), 4ul); + QCOMPARE(trans.at(0)->member, 1); + QCOMPARE(trans.at(1)->member, 2); + QCOMPARE(trans.at(2)->member, 3); + QCOMPARE(trans.at(3)->member, 4); + qDeleteAll(trans); + } + { + // specific result container with member function + QList v({1, 2, 3, 4}); + const QVector trans = Utils::transform>(v, &Struct::getMember); + QCOMPARE(trans, QVector({1.0, 2.0, 3.0, 4.0})); + } + { + // specific result container with member + QList v({1, 2, 3, 4}); + const QVector trans = Utils::transform>(v, &Struct::member); + QCOMPARE(trans, QVector({1.0, 2.0, 3.0, 4.0})); + } } void tst_Algorithm::sort()