diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index e89b3aa8c63..5af94c5d594 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -45,6 +45,7 @@ namespace Utils { + ////////////////// // anyOf ///////////////// @@ -107,61 +108,21 @@ bool contains(const T &container, F function) return anyOf(container, function); } -// Contains for normal pointers in std::vector -template class C, typename T, typename... Args> -bool contains(const C &container, typename T::element_type *other) -{ - return anyOf(container, [other](const typename C::value_type &value) { return value.get() == other; }); -} - template bool contains(const T &container, R (S::*function)() const) { return anyOf(container, function); } -template class C, typename T, typename R, typename S, typename... Args> -bool contains(const C &container, R (S::*function)() const) +template +bool contains(const C &container, R S::*member) { - return anyOf(container, function); + return anyOf(container, std::mem_fn(member)); } ////////////////// // findOr ///////////////// - -// Containers containing std::unique_ptr: -template class C, - typename T, typename D, - typename F, - typename... Args> -Q_REQUIRED_RESULT -T *findOr(const C, Args...> &container, T *other, F function) -{ - auto end = std::end(container); - auto it = std::find_if(std::begin(container), end, function); - return (it == end) ? other : it->get(); -} - -template class C, - typename T, typename D, - typename R, typename S, - typename... Args> -Q_REQUIRED_RESULT -T *findOr(const C, Args...> &container, T *other, R (S::*function)() const) -{ - return findOr(container, other, std::mem_fn(function)); -} - -template class C, typename... Args, - typename T, typename D, - typename R, typename S> -Q_REQUIRED_RESULT -T *findOr(const C, Args...> &container, T *other, R S::*member) -{ - return findOr(container, other, std::mem_fn(member)); -} - template Q_REQUIRED_RESULT typename C::value_type findOr(const C &container, typename C::value_type other, F function) @@ -190,62 +151,31 @@ typename T::value_type findOr(const T &container, typename T::value_type other, ////////////////// // findOrDefault ////////////////// - -// Containers containing std::unique_ptr: -template class C, - typename T, typename D, - typename F, - typename... Args> -Q_REQUIRED_RESULT -T *findOrDefault(const C, Args...> &container, F function) -{ - return findOr(container, static_cast(nullptr), function); -} - -template class C, - typename T, typename D, - typename R, typename S, - typename... Args> -Q_REQUIRED_RESULT -T *findOrDefault(const C, Args...> &container, R (S::*function)() const) -{ - return findOr(container, static_cast(nullptr), std::mem_fn(function)); -} - -template class C, - typename T, typename D, - typename R, typename S, - typename... Args> -Q_REQUIRED_RESULT -T *findOrDefault(const C, Args...> &container, R S::*member) -{ - return findOr(container, static_cast(nullptr), std::mem_fn(member)); -} - - // Default implementation: template Q_REQUIRED_RESULT -typename C::value_type findOrDefault(const C &container, F function) +typename std::enable_if_t::value, typename C::value_type> +findOrDefault(const C &container, F function) { return findOr(container, typename C::value_type(), function); } template Q_REQUIRED_RESULT -typename C::value_type findOrDefault(const C &container, R (S::*function)() const) +typename std::enable_if_t::value, typename C::value_type> +findOrDefault(const C &container, R (S::*function)() const) { return findOr(container, typename C::value_type(), std::mem_fn(function)); } template Q_REQUIRED_RESULT -typename C::value_type findOrDefault(const C &container, R S::*member) +typename std::enable_if_t::value, typename C::value_type> +findOrDefault(const C &container, R S::*member) { return findOr(container, typename C::value_type(), std::mem_fn(member)); } - ////////////////// // index of: ////////////////// @@ -746,30 +676,6 @@ inline void reverseForeach(const Container &c, const Op &operation) operation(*it); } -////////////////// -// toRawPointer -///////////////// -template -ResultContainer toRawPointer(const SourceContainer &sources) -{ - return transform(sources, [] (const auto &pointer) { return pointer.get(); }); -} - -template class ResultContainer, - template class SourceContainer, - typename... SCArgs> -auto toRawPointer(const SourceContainer &sources) -{ - return transform &>(sources, [] (const auto &pointer) { return pointer.get(); }); -} - -template -auto toRawPointer(const SourceContainer &sources) -{ - return transform(sources, [] (const auto &pointer) { return pointer.get(); }); -} - ////////////////// // toReferences ///////////////// diff --git a/src/libs/utils/pointeralgorithm.h b/src/libs/utils/pointeralgorithm.h new file mode 100644 index 00000000000..64550fdee6c --- /dev/null +++ b/src/libs/utils/pointeralgorithm.h @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "algorithm.h" + +#include + +namespace Utils +{ + +template +using ValueType = typename C::value_type; + +template +using PointerType = typename C::value_type::element_type*; + +////////////////// +// anyOf +///////////////// +template +bool anyOf(const C &container, PointerType p) +{ + return anyOf(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +bool anyOf(const C &container, std::nullptr_t) +{ + return anyOf(container, static_cast>(nullptr)); +} + +////////////////// +// count +///////////////// +template +int count(const C &container, PointerType p) +{ + return count(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +int count(const C &container, std::nullptr_t) +{ + return count(container, static_cast>(nullptr)); +} + +////////////////// +// allOf +///////////////// +template +bool allOf(const C &container, PointerType p) +{ + return allOf(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +int allOf(const C &container, std::nullptr_t) +{ + return allOf(container, static_cast>(nullptr)); +} + +////////////////// +// erase +///////////////// +template +void erase(C &container, PointerType p) +{ + return erase(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +int erase(const C &container, std::nullptr_t) +{ + return erase(container, static_cast>(nullptr)); +} + +////////////////// +// contains +///////////////// +template +bool contains(const C &container, PointerType p) +{ + return anyOf(container, p); +} + +template +bool contains(const C &container, std::nullptr_t) +{ + return anyOf(container, nullptr); +} + +////////////////// +// findOr +///////////////// + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, PointerType other, F function) +{ + typename C::const_iterator begin = std::begin(container); + typename C::const_iterator end = std::end(container); + + typename C::const_iterator it = std::find_if(begin, end, function); + return it == end ? other : it->get(); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, PointerType other, R (S::*function)() const) +{ + return findOr(container, other, std::mem_fn(function)); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, PointerType other, R S::*member) +{ + return findOr(container, other, std::mem_fn(member)); +} + + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, std::nullptr_t, F function) +{ + return findOr(container, static_cast>(nullptr), function); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, std::nullptr_t, R (S::*function)() const) +{ + return findOr(container, static_cast>(nullptr), function); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, std::nullptr_t, R S::*member) +{ + return findOr(container, static_cast>(nullptr), member); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, PointerType other, PointerType p) +{ + return findOr(container, other, [p](const ValueType &v) { return v.get() == p; }); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, PointerType other, std::nullptr_t) +{ + return findOr(container, other, static_cast>(nullptr)); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, std::nullptr_t, PointerType p) +{ + return findOr(container, static_cast>(nullptr), p); +} + +template +Q_REQUIRED_RESULT +PointerType findOr(const C &container, std::nullptr_t, std::nullptr_t) +{ + return findOr(container, static_cast>(nullptr), static_cast>(nullptr)); +} + +////////////////// +// findOrDefault +///////////////// +template +Q_REQUIRED_RESULT +PointerType findOrDefault(const C &container, F function) +{ + return findOr(container, static_cast>(nullptr), function); +} + +template +Q_REQUIRED_RESULT +PointerType findOrDefault(const C &container, R (S::*function)() const) +{ + return findOr(container, static_cast>(nullptr), std::mem_fn(function)); +} + +template +Q_REQUIRED_RESULT +PointerType findOrDefault(const C &container, R S::*member) +{ + return findOr(container, static_cast>(nullptr), std::mem_fn(member)); +} + +template +Q_REQUIRED_RESULT +PointerType findOrDefault(const C &container, PointerType p) +{ + return findOr(container, static_cast>(nullptr), p); +} + +template +Q_REQUIRED_RESULT +PointerType findOrDefault(const C &container, std::nullptr_t) +{ + return findOr(container, static_cast>(nullptr), static_cast>(nullptr)); +} + +////////////////// +// index of: +////////////////// +template +Q_REQUIRED_RESULT +int indexOf(const C& container, PointerType p) +{ + return indexOf(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +Q_REQUIRED_RESULT +int indexOf(const C& container, std::nullptr_t) +{ + return indexOf(container, static_cast>(nullptr)); +} + +////////////////// +// toRawPointer +///////////////// +template +ResultContainer toRawPointer(const SourceContainer &sources) +{ + return transform(sources, [] (const auto &pointer) { return pointer.get(); }); +} + +template class ResultContainer, + template class SourceContainer, + typename... SCArgs> +auto toRawPointer(const SourceContainer &sources) +{ + return transform &>(sources, [] (const auto &pointer) { return pointer.get(); }); +} + +template +auto toRawPointer(const SourceContainer &sources) +{ + return transform(sources, [] (const auto &pointer) { return pointer.get(); }); +} + +////////////////// +// take: +///////////////// +template +Q_REQUIRED_RESULT Utils::optional> take(C &container, ValueType *p) +{ + return take(container, [p](const ValueType &v) { return v.get() == p; }); +} + +template +Q_REQUIRED_RESULT Utils::optional> take(C &container, std::nullptr_t) +{ + return take(container, static_cast *>(nullptr)); +} + +////////////////// +// takeOrDefault: +///////////////// +template +Q_REQUIRED_RESULT ValueType takeOrDefault(C &container, ValueType *p) +{ + auto result = take(container, [p](const ValueType &v) { return v.get() == p; }); + return bool(result) ? result.value() : Utils::make_optional>(nullptr); +} + +template +Q_REQUIRED_RESULT ValueType takeOrDefault(C &container, std::nullptr_t) +{ + return takeOrDefault(container, static_cast *>(nullptr)); +} + +} // namespace Utils diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index f09b246ef04..342d89b4450 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -131,6 +131,7 @@ HEADERS += \ $$PWD/environment.h \ $$PWD/environmentmodel.h \ $$PWD/environmentdialog.h \ + $$PWD/pointeralgorithm.h \ $$PWD/qtcprocess.h \ $$PWD/utils_global.h \ $$PWD/reloadpromptutils.h \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 24d6c3aeea1..df02ea2d573 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -167,6 +167,7 @@ Project { "persistentsettings.cpp", "persistentsettings.h", "predicates.h", + "pointeralgorithm.h", "port.cpp", "port.h", "portlist.cpp", diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp index 88845d7e013..706b6dd91eb 100644 --- a/tests/auto/algorithm/tst_algorithm.cpp +++ b/tests/auto/algorithm/tst_algorithm.cpp @@ -48,7 +48,6 @@ private slots: void contains(); void findOr(); void findOrDefault(); - void toRawPointer(); void toReferences(); void take(); }; @@ -476,93 +475,31 @@ void tst_Algorithm::contains() QList structQlist = {2, 4, 6, 8}; QVERIFY(Utils::contains(structQlist, &Struct::isEven)); QVERIFY(!Utils::contains(structQlist, &Struct::isOdd)); - std::vector> v2; - v2.emplace_back(std::make_unique(1)); - v2.emplace_back(std::make_unique(2)); - v2.emplace_back(std::make_unique(3)); - v2.emplace_back(std::make_unique(4)); - QVERIFY(Utils::contains(v2, [](const std::unique_ptr &ip) { return *ip == 2; })); - QVERIFY(!Utils::contains(v2, [](const std::unique_ptr &ip) { return *ip == 5; })); - // Find pointers in unique_ptrs: - QVERIFY(Utils::contains(v2, v2.back().get())); - int foo = 42; - QVERIFY(!Utils::contains(v2, &foo)); } void tst_Algorithm::findOr() { std::vector v1{1, 2, 3, 4}; - QCOMPARE(Utils::findOr(v1, 6, [](int i) { return i == 2; }), 2); - QCOMPARE(Utils::findOr(v1, 6, [](int i) { return i == 5; }), 6); - std::vector> v2; - v2.emplace_back(std::make_unique(1)); - v2.emplace_back(std::make_unique(2)); - v2.emplace_back(std::make_unique(3)); - v2.emplace_back(std::make_unique(4)); - int def = 6; - QCOMPARE(Utils::findOr(v2, &def, [](const std::unique_ptr &ip) { return *ip == 2; }), v2.at(1).get()); - QCOMPARE(Utils::findOr(v2, &def, [](const std::unique_ptr &ip) { return *ip == 5; }), &def); - std::vector> v3; - v3.emplace_back(std::make_unique(1)); - v3.emplace_back(std::make_unique(3)); - v3.emplace_back(std::make_unique(5)); - v3.emplace_back(std::make_unique(7)); - Struct defS(6); - QCOMPARE(Utils::findOr(v3, &defS, &Struct::isOdd), v3.at(0).get()); - QCOMPARE(Utils::findOr(v3, &defS, &Struct::isEven), &defS); - - std::vector> v4; - v4.emplace_back(std::make_shared(1)); - v4.emplace_back(std::make_shared(3)); - v4.emplace_back(std::make_shared(5)); - v4.emplace_back(std::make_shared(7)); - std::shared_ptr sharedDefS = std::make_shared(6); - QCOMPARE(Utils::findOr(v4, sharedDefS, &Struct::isOdd), v4.at(0)); - QCOMPARE(Utils::findOr(v4, sharedDefS, &Struct::isEven), sharedDefS); + QCOMPARE(Utils::findOr(v1, 10, [](int i) { return i == 2; }), 2); + QCOMPARE(Utils::findOr(v1, 10, [](int i) { return i == 5; }), 10); } void tst_Algorithm::findOrDefault() { - std::vector v1{1, 2, 3, 4}; - QCOMPARE(Utils::findOrDefault(v1, [](int i) { return i == 2; }), 2); - QCOMPARE(Utils::findOrDefault(v1, [](int i) { return i == 5; }), 0); - std::vector> v2; - v2.emplace_back(std::make_unique(1)); - v2.emplace_back(std::make_unique(2)); - v2.emplace_back(std::make_unique(3)); - v2.emplace_back(std::make_unique(4)); - QCOMPARE(Utils::findOrDefault(v2, [](const std::unique_ptr &ip) { return *ip == 2; }), v2.at(1).get()); - QCOMPARE(Utils::findOrDefault(v2, [](const std::unique_ptr &ip) { return *ip == 5; }), static_cast(0)); - std::vector> v3; - v3.emplace_back(std::make_unique(1)); - v3.emplace_back(std::make_unique(3)); - v3.emplace_back(std::make_unique(5)); - v3.emplace_back(std::make_unique(7)); - QCOMPARE(Utils::findOrDefault(v3, &Struct::isOdd), v3.at(0).get()); - QCOMPARE(Utils::findOrDefault(v3, &Struct::isEven), static_cast(nullptr)); - - std::vector> v4; - v4.emplace_back(std::make_shared(1)); - v4.emplace_back(std::make_shared(3)); - v4.emplace_back(std::make_shared(5)); - v4.emplace_back(std::make_shared(7)); - QCOMPARE(Utils::findOrDefault(v4, &Struct::isOdd), v4.at(0)); - QCOMPARE(Utils::findOrDefault(v4, &Struct::isEven), std::shared_ptr()); -} - -void tst_Algorithm::toRawPointer() -{ - const std::vector> v; - - // same result container - const std::vector x1 = Utils::toRawPointer(v); - // different result container - const std::vector x2 = Utils::toRawPointer(v); - const QVector x3 = Utils::toRawPointer(v); - const std::list x4 = Utils::toRawPointer(v); - // different fully specified result container - const std::vector x5 = Utils::toRawPointer>(v); - const QVector x6 = Utils::toRawPointer>(v); + { + std::vector v1{1, 2, 3, 4}; + QCOMPARE(Utils::findOrDefault(v1, [](int i) { return i == 2; }), 2); + QCOMPARE(Utils::findOrDefault(v1, [](int i) { return i == 5; }), 0); + } + { + std::vector> v4; + v4.emplace_back(std::make_shared(1)); + v4.emplace_back(std::make_shared(3)); + v4.emplace_back(std::make_shared(5)); + v4.emplace_back(std::make_shared(7)); + QCOMPARE(Utils::findOrDefault(v4, &Struct::isOdd), v4.at(0)); + QCOMPARE(Utils::findOrDefault(v4, &Struct::isEven), std::shared_ptr()); + } } void tst_Algorithm::toReferences() diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 8eed70e06d2..d5a129dd0f4 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -12,6 +12,7 @@ SUBDIRS += \ externaltool \ environment \ generichighlighter \ + pointeralgorithm \ profilewriter \ treeviewfind \ toolchaincache \ diff --git a/tests/auto/pointeralgorithm/pointeralgorithm.pro b/tests/auto/pointeralgorithm/pointeralgorithm.pro new file mode 100644 index 00000000000..9a71c27da1b --- /dev/null +++ b/tests/auto/pointeralgorithm/pointeralgorithm.pro @@ -0,0 +1,4 @@ +include(../qttest.pri) + +SOURCES += tst_pointeralgorithm.cpp +OTHER_FILES += $$IDE_SOURCE_TREE/src/libs/utils/pointeralgorithm.h diff --git a/tests/auto/pointeralgorithm/pointeralgorithm.qbs b/tests/auto/pointeralgorithm/pointeralgorithm.qbs new file mode 100644 index 00000000000..838ecfe2e92 --- /dev/null +++ b/tests/auto/pointeralgorithm/pointeralgorithm.qbs @@ -0,0 +1,10 @@ +import qbs + +QtcAutotest { + name: "PointerAlgorithm autotest" + + cpp.includePaths: [project.ide_source_tree + "/src/libs"] + files: [ + "tst_pointeralgorithm.cpp", + ] +} diff --git a/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp b/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp new file mode 100644 index 00000000000..1e6404eb630 --- /dev/null +++ b/tests/auto/pointeralgorithm/tst_pointeralgorithm.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +// must get included after the containers above or gcc4.9 will have a problem using +// initializer_list related code on the templates inside algorithm.h +#include + +class tst_PointerAlgorithm : public QObject +{ + Q_OBJECT + +private slots: + void anyOf(); + void count(); + void contains(); + void findOr(); + void findOrDefault(); + void toRawPointer(); + void toReferences(); + void take(); +}; + + +int stringToInt(const QString &s) +{ + return s.toInt(); +} + +namespace { + +struct BaseStruct +{ + 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; } + +}; +} + +void tst_PointerAlgorithm::anyOf() +{ + { + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + vector.emplace_back(std::unique_ptr()); + std::vector ptrVector = Utils::toRawPointer(vector); + + QVERIFY(Utils::anyOf(vector, ptrVector.at(0))); + int foo = 42; + QVERIFY(!Utils::anyOf(vector, &foo)); + QVERIFY(Utils::anyOf(vector, nullptr)); + } + { + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + std::vector ptrVector = Utils::toRawPointer(vector); + + QVERIFY(!Utils::anyOf(vector, nullptr)); + } +} + +void tst_PointerAlgorithm::count() +{ + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::unique_ptr()); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + vector.emplace_back(std::unique_ptr()); + std::vector ptrVector = Utils::toRawPointer(vector); + + QCOMPARE(Utils::count(vector, ptrVector.at(0)), 1); + int foo = 42; + QCOMPARE(Utils::count(vector, &foo), 0); + QCOMPARE(Utils::count(vector, nullptr), 2); +} + +void tst_PointerAlgorithm::contains() +{ + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + vector.emplace_back(std::unique_ptr()); + std::vector ptrVector = Utils::toRawPointer(vector); + + QVERIFY(Utils::contains(vector, ptrVector.at(0))); + int foo = 42; + QVERIFY(!Utils::contains(vector, &foo)); + QVERIFY(Utils::contains(vector, nullptr)); +} + +void tst_PointerAlgorithm::findOr() +{ + { + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::make_unique(2)); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + vector.emplace_back(std::unique_ptr()); + std::vector ptrVector = Utils::toRawPointer(vector); + + int foo = 42; + int bar = 23; + QVERIFY(Utils::findOr(vector, &foo, ptrVector.at(0)) == ptrVector.at(0)); + QVERIFY(Utils::findOr(vector, nullptr, &foo) == nullptr); + QVERIFY(Utils::findOr(vector, &foo, nullptr) == nullptr); + QVERIFY(Utils::findOr(vector, &foo, &bar) == &foo); + + QCOMPARE(Utils::findOr(vector, &foo, + [](const std::unique_ptr &ip) { return ip && *ip == 2; }), + ptrVector.at(1)); + QCOMPARE(Utils::findOr(vector, &foo, + [](const std::unique_ptr &ip) { return ip && *ip == 43; }), + &foo); + } + { + std::vector> v3; + v3.emplace_back(std::make_unique(1)); + v3.emplace_back(std::make_unique(3)); + v3.emplace_back(std::make_unique(5)); + v3.emplace_back(std::make_unique(7)); + Struct defS(6); + QCOMPARE(Utils::findOr(v3, &defS, &Struct::isOdd), v3.at(0).get()); + QCOMPARE(Utils::findOr(v3, &defS, &Struct::isEven), &defS); + } + { + std::vector> v4; + v4.emplace_back(std::make_shared(1)); + v4.emplace_back(std::make_shared(3)); + v4.emplace_back(std::make_shared(5)); + v4.emplace_back(std::make_shared(7)); + std::shared_ptr sharedDefS = std::make_shared(6); + QCOMPARE(Utils::findOr(v4, sharedDefS, &Struct::isOdd), v4.at(0)); + QCOMPARE(Utils::findOr(v4, sharedDefS, &Struct::isEven), sharedDefS); + } +} + +void tst_PointerAlgorithm::findOrDefault() +{ + { + std::vector> vector; + vector.emplace_back(std::make_unique(5)); + vector.emplace_back(std::make_unique(6)); + vector.emplace_back(std::make_unique(7)); + vector.emplace_back(std::unique_ptr()); + std::vector ptrVector = Utils::toRawPointer(vector); + + int foo = 42; + QVERIFY(Utils::findOrDefault(vector, ptrVector.at(0)) == ptrVector.at(0)); + QVERIFY(Utils::findOrDefault(vector, &foo) == nullptr); + } + { + std::vector> v2; + v2.emplace_back(std::make_unique(1)); + v2.emplace_back(std::make_unique(2)); + v2.emplace_back(std::make_unique(3)); + v2.emplace_back(std::make_unique(4)); + QCOMPARE(Utils::findOrDefault(v2, [](const std::unique_ptr &ip) { return *ip == 2; }), v2.at(1).get()); + QCOMPARE(Utils::findOrDefault(v2, [](const std::unique_ptr &ip) { return *ip == 5; }), static_cast(nullptr)); + } + { + std::vector> v3; + v3.emplace_back(std::make_unique(1)); + v3.emplace_back(std::make_unique(3)); + v3.emplace_back(std::make_unique(5)); + v3.emplace_back(std::make_unique(7)); + QCOMPARE(Utils::findOrDefault(v3, &Struct::isOdd), v3.at(0).get()); + QCOMPARE(Utils::findOrDefault(v3, &Struct::isEven), static_cast(nullptr)); + } +} + +void tst_PointerAlgorithm::toRawPointer() +{ + const std::vector> v; + + // same result container + const std::vector x1 = Utils::toRawPointer(v); + // different result container + const std::vector x2 = Utils::toRawPointer(v); + const QVector x3 = Utils::toRawPointer(v); + const std::list x4 = Utils::toRawPointer(v); + // different fully specified result container + const std::vector x5 = Utils::toRawPointer>(v); + const QVector x6 = Utils::toRawPointer>(v); +} + +void tst_PointerAlgorithm::toReferences() +{ + // toReference + { + // std::vector -> std::vector + std::vector v; + const std::vector> x = Utils::toReferences(v); + } + { + // QList -> std::vector + QList v; + const std::vector> x = Utils::toReferences(v); + } + { + // std::vector -> QList + std::vector v; + const QList> x = Utils::toReferences(v); + } + { + // std::vector -> std::list + std::vector v; + const std::list> x = Utils::toReferences(v); + } + // toConstReference + { + // std::vector -> std::vector + const std::vector v; + const std::vector> x = Utils::toConstReferences(v); + } + { + // QList -> std::vector + const QList v; + const std::vector> x + = Utils::toConstReferences(v); + } + { + // std::vector -> QList + const std::vector v; + const QList> x = Utils::toConstReferences(v); + } + { + // std::vector -> std::list + const std::vector v; + const std::list> x + = Utils::toConstReferences(v); + } +} + +void tst_PointerAlgorithm::take() +{ + { + QList v {1, 3, 5, 6, 7, 8, 9, 11, 13, 15, 13, 16, 17}; + Utils::optional r1 = Utils::take(v, [](const Struct &s) { return s.member == 13; }); + QVERIFY(r1); + QCOMPARE(r1.value(), 13); + Utils::optional r2 = Utils::take(v, [](const Struct &s) { return s.member == 13; }); + QVERIFY(r2); + QCOMPARE(r2.value(), 13); + Utils::optional r3 = Utils::take(v, [](const Struct &s) { return s.member == 13; }); + QVERIFY(!r3); + + Utils::optional r4 = Utils::take(v, &Struct::isEven); + QVERIFY(r4); + QCOMPARE(r4.value(), 6); + } + { + QList v {0, 0, 0, 0, 0, 0, 1, 2, 3}; + Utils::optional r1 = Utils::take(v, &Struct::member); + QVERIFY(r1); + QCOMPARE(r1.value(), 1); + } +} + +QTEST_MAIN(tst_PointerAlgorithm) + +#include "tst_pointeralgorithm.moc"