[graphics/krita] /: Implement member access functions for std::find_if and std::lower_bound
Dmitry Kazakov
null at kde.org
Mon May 8 10:58:16 BST 2023
Git commit 9529c83bfce7c5257d7cc6867e5ae6a881706651 by Dmitry Kazakov.
Committed on 05/05/2023 at 11:23.
Pushed by dkazakov into branch 'master'.
Implement member access functions for std::find_if and std::lower_bound
Basically, the new functions in kismpl namespace allow us replace
weird lambdas of the form:
QList<KeyStroke>::const_iterator it =
std::find_if(m_d->keyStrokes.constBegin(),
m_d->keyStrokes.constEnd(),
[color] (const KeyStroke &s) {
return s.color == color;
});
with much more readable code:
QList<KeyStroke>::const_iterator it =
std::find_if(m_d->keyStrokes.constBegin(),
m_d->keyStrokes.constEnd(),
kismpl::mem_equal_to(&KeyStroke::color, color));
The same is possible with binary predicates used in std::lower_bound
and std::upper_bound. This code with lambdas
auto it = std::lower_bound(m_stops.begin(), m_stops.end(),
KoGradientStop(t, KoColor(), COLORSTOP),
[](const KoGradientStop& a, const KoGradientStop& b) {
return a.position < b.position;
});
can be replaces with a readable function like this:
auto it = std::lower_bound(m_stops.begin(), m_stops.end(),
KoGradientStop(t, KoColor(), COLORSTOP),
kismpl::mem_less(&KoGradientStop::position));
This approach is inspired from the Lager library
CC:kimageshop at kde.org
M +387 -0 libs/global/KisMpl.h
M +5 -0 libs/global/kis_shared_ptr.h
M +1 -4 libs/image/kis_stroke.cpp
M +2 -6 libs/image/lazybrush/kis_colorize_mask.cpp
M +283 -1 libs/image/tests/KisMplTest.cpp
M +10 -1 libs/image/tests/KisMplTest.h
M +5 -7 libs/pigment/resources/KoStopGradient.cpp
M +1 -3 libs/ui/KisView.cpp
M +1 -2 libs/ui/animation/VideoExportOptionsDialog.cpp
M +1 -3 libs/ui/brushhud/kis_brush_hud_properties_config.cpp
M +3 -3 libs/ui/input/kis_input_manager.cpp
M +3 -3 libs/widgetutils/KisRecentFilesManager.cpp
M +3 -3 plugins/dockers/layerdocker/NodeToolTip.cpp
M +1 -3 plugins/paintops/defaultpaintops/brush/KisDabRenderingQueue.cpp
M +2 -2 plugins/paintops/spray/KisSprayRandomDistributions.cpp
https://invent.kde.org/graphics/krita/commit/9529c83bfce7c5257d7cc6867e5ae6a881706651
diff --git a/libs/global/KisMpl.h b/libs/global/KisMpl.h
index b1d3ec62dc9..386136f63de 100644
--- a/libs/global/KisMpl.h
+++ b/libs/global/KisMpl.h
@@ -143,6 +143,393 @@ std::optional<T> fold_optional(Fun &&fun, Args &&...args) {
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
+namespace detail {
+
+template<typename Op, typename Class, typename MemType, typename PtrType>
+struct mem_checker;
+
+template<typename Op, typename Class, typename MemType>
+struct mem_checker<Op, Class, MemType, MemType Class::*>
+{
+ bool operator() (const Class &object) const {
+ Op op;
+ return op(object.*ptr, value);
+ }
+
+ bool operator() (Class *object) const {
+ Op op;
+ return op((*object).*ptr, value);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &object) const {
+ Op op;
+ return op((*object).*ptr, value);
+ }
+
+ MemType Class::* ptr;
+ const MemType value;
+};
+
+template<typename Op, typename Class, typename MemType>
+struct mem_checker<Op, Class, MemType, MemType (Class::*)() const>
+{
+ bool operator() (const Class &object) const {
+ Op op;
+ return op((object.*ptr)(), value);
+ }
+
+ bool operator() (Class *object) const {
+ Op op;
+ return op(((*object).*ptr)(), value);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &object) const {
+ Op op;
+ return op(((*object).*ptr)(), value);
+ }
+
+ MemType (Class::*ptr)() const;
+ const MemType value;
+};
+
+template<typename Op, typename Class, typename MemType, typename PtrType>
+struct mem_compare;
+
+template<typename Op, typename Class, typename MemType>
+struct mem_compare<Op, Class, MemType, MemType Class::*>
+{
+ bool operator() (const Class &lhs, const Class &rhs) const {
+ Op op;
+ return op(lhs.*ptr, rhs.*ptr);
+ }
+
+ bool operator() (const Class &lhs, const MemType &rhs) const {
+ Op op;
+ return op(lhs.*ptr, rhs);
+ }
+
+ bool operator() (const MemType &lhs, const Class &rhs) const {
+ Op op;
+ return op(lhs, rhs.*ptr);
+ }
+
+ bool operator() (Class *lhs, Class *rhs) const {
+ Op op;
+ return op((*lhs).*ptr, (*rhs).*ptr);
+ }
+
+ bool operator() (Class *lhs, const MemType &rhs) const {
+ Op op;
+ return op((*lhs).*ptr, rhs);
+ }
+
+ bool operator() (const MemType &lhs, Class *rhs) const {
+ Op op;
+ return op(lhs, (*rhs).*ptr);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &lhs, const Ptr &rhs) const {
+ Op op;
+ return op((*lhs).*ptr, (*rhs).*ptr);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &lhs, const MemType &rhs) const {
+ Op op;
+ return op((*lhs).*ptr, rhs);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const MemType &lhs, const Ptr &rhs) const {
+ Op op;
+ return op(lhs, (*rhs).*ptr);
+ }
+
+ MemType Class::* ptr;
+};
+
+template<typename Op, typename Class, typename MemType>
+struct mem_compare<Op, Class, MemType, MemType (Class::*)() const>
+{
+ bool operator() (const Class &lhs, const Class &rhs) const {
+ Op op;
+ return op((lhs.*ptr)(), (rhs.*ptr)());
+ }
+
+ bool operator() (const Class &lhs, const MemType &rhs) const {
+ Op op;
+ return op((lhs.*ptr)(), rhs);
+ }
+
+ bool operator() (const MemType &lhs, const Class &rhs) const {
+ Op op;
+ return op(lhs, (rhs.*ptr)());
+ }
+
+ bool operator() (Class *lhs, Class *rhs) const {
+ Op op;
+ return op(((*lhs).*ptr)(), ((*rhs).*ptr)());
+ }
+
+ bool operator() (Class *lhs, const MemType &rhs) const {
+ Op op;
+ return op(((*lhs).*ptr)(), rhs);
+ }
+
+ bool operator() (const MemType &lhs, Class *rhs) const {
+ Op op;
+ return op(lhs, ((*rhs).*ptr)());
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &lhs, const Ptr &rhs) const {
+ Op op;
+ return op(((*lhs).*ptr)(), ((*rhs).*ptr)());
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const Ptr &lhs, const MemType &rhs) const {
+ Op op;
+ return op(((*lhs).*ptr)(), rhs);
+ }
+
+ template <typename Ptr, typename = std::void_t<typename Ptr::element_type>>
+ bool operator() (const MemType &lhs, const Ptr &rhs) const {
+ Op op;
+ return op(lhs, ((*rhs).*ptr)());
+ }
+
+ MemType (Class::*ptr)() const;
+};
+
+
+} // detail
+
+/**
+ * @brief mem_equal_to is an unary functor that compares a member of the object to
+ * a given value
+ *
+ * The functor is supposed to be used in `std::find_if` and other standard algorithms.
+ * It can automatically dereference a pointer-to-member or a pointer-to-method.
+ *
+ * * Usage:
+ *
+ * \code{.cpp}
+ *
+ * struct Struct {
+ * Struct (int _id) : id(_id) {}
+ *
+ * int id = -1;
+ * int idConstFunc() const {
+ * return id;
+ * }
+ * };
+ *
+ * std::vector<Struct> vec({{0},{1},{2},{3}});
+ *
+ * // find an element, which has member 'id' set to 1
+ * auto it1 = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, 1));
+ *
+ * // find an element, whose member function 'idConstFunc()' returns 1
+ * auto it2 = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::idConstFunc, 1));
+ *
+ * // the functor can automatically dereference pointers and shared pointers
+ * std::vector<std::shared_ptr<Struct>> vec({std::make_shared<Struct>(0),
+ * std::make_shared<Struct>(1),
+ * std::make_shared<Struct>(2),
+ * std::make_shared<Struct>(3),
+ * std::make_shared<Struct>(4)});
+ *
+ * // the shared pointer is automatically lifted by the functor
+ * auto it3 = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, 1));
+ *
+ * \endcode
+ */
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value) {
+ return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, MemTypeNoRef Class::*>{ptr, std::forward<MemType>(value)};
+}
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_equal_to(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
+ return detail::mem_checker<std::equal_to<>, Class, MemTypeNoRef, MemTypeNoRef (Class::*)() const>{ptr, std::forward<MemType>(value)};
+}
+
+/**
+ * @brief mem_less is an unary functor that compares a member of the object to
+ * a given value
+ *
+ * @see mem_equal_to
+ */
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_less(MemTypeNoRef Class::*ptr, MemType &&value) {
+ return detail::mem_checker<std::less<>, Class, MemTypeNoRef, MemTypeNoRef Class::*>{ptr, std::forward<MemType>(value)};
+}
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_less(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
+ return detail::mem_checker<std::less<>, Class, MemTypeNoRef, MemTypeNoRef (Class::*)() const>{ptr, std::forward<MemType>(value)};
+}
+
+/**
+ * @brief mem_less_equal is an unary functor that compares a member of the object to
+ * a given value
+ *
+ * @see mem_equal_to
+ */
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_less_equal(MemTypeNoRef Class::*ptr, MemType &&value) {
+ return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, MemTypeNoRef Class::*>{ptr, std::forward<MemType>(value)};
+}
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_less_equal(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
+ return detail::mem_checker<std::less_equal<>, Class, MemTypeNoRef, MemTypeNoRef (Class::*)() const>{ptr, std::forward<MemType>(value)};
+}
+
+/**
+ * @brief mem_greater is an unary functor that compares a member of the object to
+ * a given value
+ *
+ * @see mem_equal_to
+ */
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_greater(MemTypeNoRef Class::*ptr, MemType &&value) {
+ return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, MemTypeNoRef Class::*>{ptr, std::forward<MemType>(value)};
+}
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_greater(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
+ return detail::mem_checker<std::greater<>, Class, MemTypeNoRef, MemTypeNoRef (Class::*)() const>{ptr, std::forward<MemType>(value)};
+}
+
+/**
+ * @brief mem_greater_equal is an unary functor that compares a member of the object to
+ * a given value
+ *
+ * @see mem_equal_to
+ */
+
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_greater_equal(MemTypeNoRef Class::*ptr, MemType &&value) {
+ return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, MemTypeNoRef Class::*>{ptr, std::forward<MemType>(value)};
+}
+
+template<typename Class, typename MemType, typename MemTypeNoRef = std::remove_reference_t<MemType>>
+inline auto mem_greater_equal(MemTypeNoRef (Class::*ptr)() const, MemType &&value) {
+ return detail::mem_checker<std::greater_equal<>, Class, MemTypeNoRef, MemTypeNoRef (Class::*)() const>{ptr, std::forward<MemType>(value)};
+}
+
+/**
+ * @brief mem_less is a binary functor that compares a member of the object to a
+ * given value or two objects based on the value of their members
+ *
+ * The functor is supposed to be used in `std::lower_bound` and other standard algorithms.
+ * It can automatically dereference a pointer-to-member or a pointer-to-method.
+ *
+ * * Usage:
+ *
+ * \code{.cpp}
+ *
+ * struct Struct {
+ * Struct (int _id) : id(_id) {}
+ *
+ * int id = -1;
+ * int idConstFunc() const {
+ * return id;
+ * }
+ * };
+ *
+ * std::vector<Struct> vec({{0},{1},{2},{3}});
+ *
+ * // find the first element, whose 'id' is not less that 1
+ * auto it1 = std::lower_bound(vec.begin(), vec.end(), 1, kismpl::mem_less(&Struct::id));
+ *
+ * // find the first element, whose 'id' retunred by 'idConstFunc()' is not less that 1
+ * auto it2 = std::lower_bound(vec.begin(), vec.end(), 1, kismpl::mem_less(&Struct::idConstFunc, 1));
+ *
+ * // the functor can automatically dereference pointers and shared pointers
+ * std::vector<std::shared_ptr<Struct>> vec({std::make_shared<Struct>(0),
+ * std::make_shared<Struct>(1),
+ * std::make_shared<Struct>(2),
+ * std::make_shared<Struct>(3),
+ * std::make_shared<Struct>(4)});
+ *
+ * // the shared pointer is automatically lifted by the functor
+ * auto it3 = std::lower_bound(vec.begin(), vec.end(), 1, kismpl::mem_less(&Struct::id));
+ *
+ * \endcode
+ */
+
+template<typename Class, typename MemType>
+inline auto mem_less(MemType Class::*ptr) {
+ return detail::mem_compare<std::less<>, Class, MemType, MemType Class::*>{ptr};
+}
+
+template<typename Class, typename MemType>
+inline auto mem_less(MemType (Class::*ptr)() const) {
+ return detail::mem_compare<std::less<>, Class, MemType, MemType (Class::*)() const>{ptr};
+}
+
+/**
+ * @brief mem_less_equal is a binary functor that compares a member of the object to a
+ * given value or two objects based on the value of their members
+ *
+ * @see mem_less
+ */
+template<typename Class, typename MemType>
+inline auto mem_less_equal(MemType Class::*ptr) {
+ return detail::mem_compare<std::less_equal<>, Class, MemType, MemType Class::*>{ptr};
+}
+
+template<typename Class, typename MemType>
+inline auto mem_less_equal(MemType (Class::*ptr)() const) {
+ return detail::mem_compare<std::less_equal<>, Class, MemType, MemType (Class::*)() const>{ptr};
+}
+
+/**
+ * @brief mem_greater is a binary functor that compares a member of the object to a
+ * given value or two objects based on the value of their members
+ *
+ * @see mem_less
+ */
+
+template<typename Class, typename MemType>
+inline auto mem_greater(MemType Class::*ptr) {
+ return detail::mem_compare<std::greater<>, Class, MemType, MemType Class::*>{ptr};
+}
+
+template<typename Class, typename MemType>
+inline auto mem_greater(MemType (Class::*ptr)() const) {
+ return detail::mem_compare<std::greater<>, Class, MemType, MemType (Class::*)() const>{ptr};
+}
+
+/**
+ * @brief mem_greater_equal is a binary functor that compares a member of the object to a
+ * given value or two objects based on the value of their members
+ *
+ * @see mem_less
+ */
+
+template<typename Class, typename MemType>
+inline auto mem_greater_equal(MemType Class::*ptr) {
+ return detail::mem_compare<std::greater_equal<>, Class, MemType, MemType Class::*>{ptr};
+}
+
+template<typename Class, typename MemType>
+inline auto mem_greater_equal(MemType (Class::*ptr)() const) {
+ return detail::mem_compare<std::greater_equal<>, Class, MemType, MemType (Class::*)() const>{ptr};
+}
+
+
} // namespace kismpl
#endif // KISMPL_H
diff --git a/libs/global/kis_shared_ptr.h b/libs/global/kis_shared_ptr.h
index cc00f73a235..0d41a3c2eb7 100644
--- a/libs/global/kis_shared_ptr.h
+++ b/libs/global/kis_shared_ptr.h
@@ -57,6 +57,9 @@ class KisSharedPtr
{
friend class KisWeakSharedPtr<T>;
public:
+ using element_type = T;
+ using weak_type = KisWeakSharedPtr<T>;
+
/**
* Creates a null pointer.
*/
@@ -235,6 +238,8 @@ class KisWeakSharedPtr
{
friend class KisSharedPtr<T>;
public:
+ using element_type = T;
+
/**
* Creates a null pointer.
*/
diff --git a/libs/image/kis_stroke.cpp b/libs/image/kis_stroke.cpp
index 75c639c5525..012b2aa219f 100644
--- a/libs/image/kis_stroke.cpp
+++ b/libs/image/kis_stroke.cpp
@@ -89,10 +89,7 @@ void KisStroke::addMutatedJobs(const QVector<KisStrokeJobData *> list)
// the stroke.
auto it = std::find_if(m_jobsQueue.begin(), m_jobsQueue.end(),
- [] (KisStrokeJob *job) {
- return job->isOwnJob();
- });
-
+ std::mem_fn(&KisStrokeJob::isOwnJob));
Q_FOREACH (KisStrokeJobData *data, list) {
it = m_jobsQueue.insert(it, new KisStrokeJob(m_dabStrategy.data(), data, worksOnLevelOfDetail(), true));
diff --git a/libs/image/lazybrush/kis_colorize_mask.cpp b/libs/image/lazybrush/kis_colorize_mask.cpp
index a6b1a0deda9..5c335c969f4 100644
--- a/libs/image/lazybrush/kis_colorize_mask.cpp
+++ b/libs/image/lazybrush/kis_colorize_mask.cpp
@@ -684,9 +684,7 @@ void KisColorizeMask::setCurrentColor(const KoColor &_color)
QList<KeyStroke>::const_iterator it =
std::find_if(m_d->keyStrokes.constBegin(),
m_d->keyStrokes.constEnd(),
- [color] (const KeyStroke &s) {
- return s.color == color;
- });
+ kismpl::mem_equal_to(&KeyStroke::color, color));
KisPaintDeviceSP activeDevice;
bool newKeyStroke = false;
@@ -958,9 +956,7 @@ void KisColorizeMask::removeKeyStroke(const KoColor &_color)
QList<KeyStroke>::iterator it =
std::find_if(m_d->keyStrokes.begin(),
m_d->keyStrokes.end(),
- [color] (const KeyStroke &s) {
- return s.color == color;
- });
+ kismpl::mem_equal_to(&KeyStroke::color, color));
KIS_SAFE_ASSERT_RECOVER_RETURN(it != m_d->keyStrokes.end());
diff --git a/libs/image/tests/KisMplTest.cpp b/libs/image/tests/KisMplTest.cpp
index c716f7f02ea..a8daf601a63 100644
--- a/libs/image/tests/KisMplTest.cpp
+++ b/libs/image/tests/KisMplTest.cpp
@@ -13,7 +13,7 @@
#include <KisMpl.h>
-void KisMplTest::test()
+void KisMplTest::testFoldOptional()
{
std::optional<int> a(0x1);
std::optional<int> b(0x2);
@@ -34,4 +34,286 @@ void KisMplTest::test()
}
+namespace {
+struct Struct {
+ Struct(int _id) : id(_id) {}
+
+ int id = -1;
+ int idFunc() {
+ return id;
+ }
+ int idConstFunc() const {
+ return id;
+ }
+
+ int overloaded() const {
+ return id;
+ }
+
+ int overloaded() {
+ return id;
+ }
+
+};
+
+struct StructExplicit {
+ explicit StructExplicit (int _id) : id(_id) {}
+
+ int id = -1;
+ int idConstFunc() const {
+ return id;
+ }
+};
+}
+
+void KisMplTest::testMemberOperatorsEqualTo()
+{
+ int v = 1;
+ int &vref = v;
+ const int &vconstref = v;
+
+
+ std::vector<Struct> vec({{0},{1},{2},{3}});
+
+ ////////////////////////////////////////
+ // compare member variable against value
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, v));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member variable against reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, vref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member variable against const reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, vconstref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ ////////////////////////////////////////
+ // compare member function against value
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::idConstFunc, v));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member function against reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, vref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member function against const reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, vconstref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ ////////////////////////////////////////
+ // compare overloaded member function against value
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::overloaded, v));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member function against reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::overloaded, vref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+
+ // compare member function against const reference
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::overloaded, vconstref));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+}
+
+void KisMplTest::testMemberOperatorsEqualToPointer()
+{
+ std::vector<Struct> vec_base({{0},{1},{2},{3},{4}});
+ std::vector<Struct*> vec({&vec_base[0], &vec_base[1], &vec_base[2], &vec_base[3], &vec_base[3]});
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, 1));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+}
+
+void KisMplTest::testMemberOperatorsEqualToStdSharedPtr()
+{
+ std::vector<std::shared_ptr<Struct>> vec({std::make_shared<Struct>(0),
+ std::make_shared<Struct>(1),
+ std::make_shared<Struct>(2),
+ std::make_shared<Struct>(3),
+ std::make_shared<Struct>(4)});
+
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, 1));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+}
+
+void KisMplTest::testMemberOperatorsEqualToQSharedPointer()
+{
+ std::vector<QSharedPointer<Struct>> vec({QSharedPointer<Struct>::create(0),
+ QSharedPointer<Struct>::create(1),
+ QSharedPointer<Struct>::create(2),
+ QSharedPointer<Struct>::create(3),
+ QSharedPointer<Struct>::create(4)});
+
+ {
+ auto it = std::find_if(vec.begin(), vec.end(), kismpl::mem_equal_to(&Struct::id, 1));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 1);
+ }
+}
+
+void KisMplTest::testMemberOperatorsLess()
+{
+ {
+ std::vector<StructExplicit> vec({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+ {
+ std::vector<StructExplicit> vec({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+
+ {
+ std::vector<StructExplicit> vec_base({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+ std::vector<StructExplicit*> vec({&vec_base[0], &vec_base[1], &vec_base[2], &vec_base[3], &vec_base[3]});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+ {
+ std::vector<StructExplicit> vec_base({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+ std::vector<StructExplicit*> vec({&vec_base[0], &vec_base[1], &vec_base[2], &vec_base[3], &vec_base[3]});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+ {
+ std::vector<std::shared_ptr<StructExplicit>> vec({std::make_shared<StructExplicit>(0),
+ std::make_shared<StructExplicit>(1),
+ std::make_shared<StructExplicit>(2),
+ std::make_shared<StructExplicit>(3),
+ std::make_shared<StructExplicit>(4)});
+
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+ {
+ std::vector<std::shared_ptr<StructExplicit>> vec({std::make_shared<StructExplicit>(0),
+ std::make_shared<StructExplicit>(1),
+ std::make_shared<StructExplicit>(2),
+ std::make_shared<StructExplicit>(3),
+ std::make_shared<StructExplicit>(4)});
+
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+}
+
+void KisMplTest::testMemberOperatorsLessEqual()
+{
+ {
+ std::vector<StructExplicit> vec({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less_equal(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 3);
+ }
+
+ {
+ std::vector<StructExplicit> vec({StructExplicit(0),StructExplicit(1),StructExplicit(2),StructExplicit(3),StructExplicit(4)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_less_equal(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 3);
+ }
+}
+
+void KisMplTest::testMemberOperatorsGreater()
+{
+ {
+ std::vector<StructExplicit> vec({StructExplicit(4),StructExplicit(3),StructExplicit(2),StructExplicit(1),StructExplicit(0)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_greater(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+
+ {
+ std::vector<StructExplicit> vec({StructExplicit(4),StructExplicit(3),StructExplicit(2),StructExplicit(1),StructExplicit(0)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_greater(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 2);
+ }
+}
+
+void KisMplTest::testMemberOperatorsGreaterEqual()
+{
+ {
+ std::vector<StructExplicit> vec({StructExplicit(4),StructExplicit(3),StructExplicit(2),StructExplicit(1),StructExplicit(0)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_greater_equal(&StructExplicit::id));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 3);
+ }
+
+ {
+ std::vector<StructExplicit> vec({StructExplicit(4),StructExplicit(3),StructExplicit(2),StructExplicit(1),StructExplicit(0)});
+
+ auto it = std::lower_bound(vec.begin(), vec.end(), 2, kismpl::mem_greater_equal(&StructExplicit::idConstFunc));
+ QVERIFY(it != vec.end());
+ QCOMPARE(std::distance(vec.begin(), it), 3);
+ }
+}
+
+
SIMPLE_TEST_MAIN(KisMplTest)
diff --git a/libs/image/tests/KisMplTest.h b/libs/image/tests/KisMplTest.h
index fc1acdef48c..e983682d7f2 100644
--- a/libs/image/tests/KisMplTest.h
+++ b/libs/image/tests/KisMplTest.h
@@ -12,7 +12,16 @@ class KisMplTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
- void test();
+ void testFoldOptional();
+ void testMemberOperatorsEqualTo();
+ void testMemberOperatorsEqualToPointer();
+ void testMemberOperatorsEqualToStdSharedPtr();
+ void testMemberOperatorsEqualToQSharedPointer();
+
+ void testMemberOperatorsLess();
+ void testMemberOperatorsLessEqual();
+ void testMemberOperatorsGreater();
+ void testMemberOperatorsGreaterEqual();
};
#endif // KISMPLTEST_H
diff --git a/libs/pigment/resources/KoStopGradient.cpp b/libs/pigment/resources/KoStopGradient.cpp
index a671f673cd6..a72974bd05b 100644
--- a/libs/pigment/resources/KoStopGradient.cpp
+++ b/libs/pigment/resources/KoStopGradient.cpp
@@ -143,9 +143,8 @@ bool KoStopGradient::stopsAt(KoGradientStop& leftStop, KoGradientStop& rightStop
} else {
// we have at least two color stops
// -> find the two stops which frame our t
- auto it = std::lower_bound(m_stops.begin(), m_stops.end(), KoGradientStop(t, KoColor(), COLORSTOP), [](const KoGradientStop& a, const KoGradientStop& b) {
- return a.position < b.position;
- });
+ auto it = std::lower_bound(m_stops.begin(), m_stops.end(), KoGradientStop(t, KoColor(), COLORSTOP),
+ kismpl::mem_less(&KoGradientStop::position));
leftStop = *(it - 1);
rightStop = *(it);
return true;
@@ -257,10 +256,9 @@ QList<int> KoStopGradient::requiredCanvasResources() const
{
QList<int> result;
- if (std::find_if(m_stops.begin(), m_stops.end(),
- [] (const KoGradientStop &stop) {
- return stop.type != COLORSTOP;
- }) != m_stops.end()) {
+ if (std::find_if_not(m_stops.begin(), m_stops.end(),
+ kismpl::mem_equal_to(&KoGradientStop::type, COLORSTOP))
+ != m_stops.end()) {
result << KoCanvasResource::ForegroundColor << KoCanvasResource::BackgroundColor;
}
diff --git a/libs/ui/KisView.cpp b/libs/ui/KisView.cpp
index af8c4144d46..67b3834b6e1 100644
--- a/libs/ui/KisView.cpp
+++ b/libs/ui/KisView.cpp
@@ -622,9 +622,7 @@ void KisView::dropEvent(QDropEvent *event)
if (reference) {
if (data->hasUrls()) {
const auto &urls = data->urls();
- const auto url = std::find_if(urls.constBegin(), urls.constEnd(), [&](const QUrl &url) {
- return url.isLocalFile();
- });
+ const auto url = std::find_if(urls.constBegin(), urls.constEnd(), std::mem_fn(&QUrl::isLocalFile));
if (url != urls.constEnd()) {
reference->setFilename((*url).toLocalFile());
}
diff --git a/libs/ui/animation/VideoExportOptionsDialog.cpp b/libs/ui/animation/VideoExportOptionsDialog.cpp
index 2fbd86f4d69..3e3817b4a1d 100644
--- a/libs/ui/animation/VideoExportOptionsDialog.cpp
+++ b/libs/ui/animation/VideoExportOptionsDialog.cpp
@@ -417,8 +417,7 @@ void KisVideoExportOptionsDialog::setHDRConfiguration(bool value) {
int findIndexById(const QString &id, const QVector<KoID> &ids)
{
int index = -1;
- auto it = std::find_if(ids.begin(), ids.end(),
- [id] (const KoID &item) { return item.id() == id; });
+ auto it = std::find_if(ids.begin(), ids.end(), kismpl::mem_equal_to(&KoID::id, id));
if (it != ids.end()) {
index = std::distance(ids.begin(), it);
}
diff --git a/libs/ui/brushhud/kis_brush_hud_properties_config.cpp b/libs/ui/brushhud/kis_brush_hud_properties_config.cpp
index acf61fb67a1..df487f29e96 100644
--- a/libs/ui/brushhud/kis_brush_hud_properties_config.cpp
+++ b/libs/ui/brushhud/kis_brush_hud_properties_config.cpp
@@ -109,9 +109,7 @@ void KisBrushHudPropertiesConfig::filterProperties(
Q_FOREACH (const QString &id, selectedIds) {
auto it = std::find_if(skippedProperties->begin(),
skippedProperties->end(),
- [id] (KisUniformPaintOpPropertySP prop) {
- return prop->id() == id;
- });
+ kismpl::mem_equal_to(&KisUniformPaintOpProperty::id, id));
if (it != skippedProperties->end()) {
*chosenProperties << *it;
diff --git a/libs/ui/input/kis_input_manager.cpp b/libs/ui/input/kis_input_manager.cpp
index b514d32b60f..5c77319bf15 100644
--- a/libs/ui/input/kis_input_manager.cpp
+++ b/libs/ui/input/kis_input_manager.cpp
@@ -132,12 +132,12 @@ void KisInputManager::attachPriorityEventFilter(QObject *filter, int priority)
Private::PriorityList::iterator end = d->priorityEventFilter.end();
it = std::find_if(begin, end,
- [filter] (const Private::PriorityPair &a) { return a.second == filter; });
+ kismpl::mem_equal_to(&Private::PriorityPair::second, filter));
if (it != end) return;
it = std::find_if(begin, end,
- [priority] (const Private::PriorityPair &a) { return a.first > priority; });
+ kismpl::mem_greater(&Private::PriorityPair::first, priority));
d->priorityEventFilter.insert(it, qMakePair(priority, filter));
d->priorityEventFilterSeqNo++;
@@ -149,7 +149,7 @@ void KisInputManager::detachPriorityEventFilter(QObject *filter)
Private::PriorityList::iterator end = d->priorityEventFilter.end();
it = std::find_if(it, end,
- [filter] (const Private::PriorityPair &a) { return a.second == filter; });
+ kismpl::mem_equal_to(&Private::PriorityPair::second, filter));
if (it != end) {
d->priorityEventFilter.erase(it);
diff --git a/libs/widgetutils/KisRecentFilesManager.cpp b/libs/widgetutils/KisRecentFilesManager.cpp
index 493c26f3ffb..b0536adc4f6 100644
--- a/libs/widgetutils/KisRecentFilesManager.cpp
+++ b/libs/widgetutils/KisRecentFilesManager.cpp
@@ -16,6 +16,7 @@
#include <kconfig.h>
#include <kconfiggroup.h>
#include <ksharedconfig.h>
+#include <KisMpl.h>
class KisRecentFilesManager::Private
{
@@ -54,9 +55,8 @@ bool KisRecentFilesManager::Private::containsUrl(const QUrl &url) const
int KisRecentFilesManager::Private::indexOfUrl(const QUrl &url) const
{
- auto found = std::find_if(m_entries.constBegin(), m_entries.constEnd(), [url](const KisRecentFilesEntry &item) {
- return item.m_url == url;
- });
+ auto found = std::find_if(m_entries.constBegin(), m_entries.constEnd(),
+ kismpl::mem_equal_to(&KisRecentFilesEntry::m_url, url));
if (found == m_entries.constEnd()) {
return -1;
} else {
diff --git a/plugins/dockers/layerdocker/NodeToolTip.cpp b/plugins/dockers/layerdocker/NodeToolTip.cpp
index d2996a0eead..62ea6887cf9 100644
--- a/plugins/dockers/layerdocker/NodeToolTip.cpp
+++ b/plugins/dockers/layerdocker/NodeToolTip.cpp
@@ -59,9 +59,9 @@ QTextDocument *NodeToolTip::createDocument(const QModelIndex &index)
QString errorMessage;
{
auto it = std::find_if(properties.begin(), properties.end(),
- [] (const KisBaseNode::Property &prop) {
- return prop.id == KisLayerPropertiesIcons::layerError.id();
- });
+ kismpl::mem_equal_to(&KisBaseNode::Property::id,
+ KisLayerPropertiesIcons::layerError.id()));
+
if (it != properties.end()) {
doc->addResource(QTextDocument::ImageResource, QUrl("data:warn_symbol"), it->onIcon.pixmap(QSize(32,32)).toImage());
errorMessage = QString("<table align=\"center\" border=\"0\"><tr valign=\"middle\"><td align=\"right\"><img src=\"data:warn_symbol\"></td><td align=\"left\"><b>%1</b></td></tr></table>").arg(it->state.toString());
diff --git a/plugins/paintops/defaultpaintops/brush/KisDabRenderingQueue.cpp b/plugins/paintops/defaultpaintops/brush/KisDabRenderingQueue.cpp
index e22ede016bf..7e6baed4228 100644
--- a/plugins/paintops/defaultpaintops/brush/KisDabRenderingQueue.cpp
+++ b/plugins/paintops/defaultpaintops/brush/KisDabRenderingQueue.cpp
@@ -202,9 +202,7 @@ QList<KisDabRenderingJobSP> KisDabRenderingQueue::notifyJobFinished(int seqNo, i
*/
auto finishedJobIt =
std::lower_bound(m_d->jobs.begin(), m_d->jobs.end(), seqNo,
- [] (KisDabRenderingJobSP job, int seqNo) {
- return job->seqNo < seqNo;
- });
+ kismpl::mem_less(&KisDabRenderingJob::seqNo));
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(finishedJobIt != m_d->jobs.end(), dependentJobs);
KisDabRenderingJobSP finishedJob = *finishedJobIt;
diff --git a/plugins/paintops/spray/KisSprayRandomDistributions.cpp b/plugins/paintops/spray/KisSprayRandomDistributions.cpp
index 27c4d855267..5498e4a0056 100644
--- a/plugins/paintops/spray/KisSprayRandomDistributions.cpp
+++ b/plugins/paintops/spray/KisSprayRandomDistributions.cpp
@@ -7,6 +7,7 @@
#include <cmath>
#include <kis_assert.h>
+#include <KisMpl.h>
#include "KisSprayRandomDistributions.h"
@@ -152,8 +153,7 @@ public:
// Find the first sample that has cdf greater than the passed value
auto sampleIterator =
std::upper_bound(samples.begin(), samples.end(), SampleInfo{0.0, randomValue, 0.0},
- [](const SampleInfo &a, const SampleInfo &b) -> bool { return a.cdfAtX < b.cdfAtX; }
- );
+ kismpl::mem_less(&SampleInfo::cdfAtX));
const double t = (randomValue - (sampleIterator - 1)->cdfAtX) * sampleIterator->oneOverCdfDy;
return (sampleIterator - 1)->x + t * (sampleIterator->x - (sampleIterator - 1)->x);
}
More information about the kimageshop
mailing list