From f6f2d388212d4e22f0f73d0bd982be41b57f3b60 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Tue, 25 Oct 2016 22:41:10 +0100 Subject: [PATCH] refs #784 Added helper class for using CMemoTable with containers of value objects. --- src/blackmisc/memotable.h | 52 ++++++++++++++++++++++++++++++++++++++ src/blackmisc/typetraits.h | 12 +++++++++ 2 files changed, 64 insertions(+) diff --git a/src/blackmisc/memotable.h b/src/blackmisc/memotable.h index d976cc919..456a6681b 100644 --- a/src/blackmisc/memotable.h +++ b/src/blackmisc/memotable.h @@ -46,6 +46,58 @@ namespace BlackMisc CSequence m_list; CDictionary m_dict; }; + + /*! + * Helper class for memoizing members of a value object. + */ + template + struct CMemoHelper + { + //! Memoizer for Ts. Other types are passed through. + class CMemoizer : private CMemoTable... + { + public: + //! If T is in Ts, return the index of member in the memo table. + template ::value, int> = 0> + int maybeMemoize(const T &member) { return this->CMemoTable::getIndex(member); } + + //! If T is not in Ts, return member. + template ::value, int> = 0> + const T &maybeMemoize(const T &member) { return member; } + + //! Return the values in the T table as a flat list. + template + const CSequence &getTable() const { return this->CMemoTable::getTable(); } + }; + + //! Unmemoizer for Ts. Other types are passed through. + class CUnmemoizer : private CSequence... + { + public: + //! Return reference to the flat list T table. + template + CSequence &getTable() { return *this; } + + //! If T is in Ts, return proxy that will assign to member through the value at the given index in the flat list. + template ::value, int> = 0> + auto maybeUnmemoize(T &member) const + { + struct Memo + { + int index; + T &member; + const CSequence &list; + int &get() { return index; } + ~Memo() { if (index >= 0) { member = list[index]; } } + }; + return Memo { -1, member, static_cast &>(*this) }; + } + + //! If T is not in Ts, return member as std::reference_wrapper. + template ::value, int> = 0> + auto maybeUnmemoize(T &member) const { return std::ref(member); } + }; + }; } #endif diff --git a/src/blackmisc/typetraits.h b/src/blackmisc/typetraits.h index 268f2f57a..9ed1236fc 100644 --- a/src/blackmisc/typetraits.h +++ b/src/blackmisc/typetraits.h @@ -162,6 +162,18 @@ namespace BlackMisc struct TIsEqualityComparable() == std::declval())>> : public std::true_type {}; //! \endcond + /*! + * Trait that detects if a type is a member of a parameter pack. + */ + template + struct TIsOneOf : public std::false_type {}; + //! \cond + template + struct TIsOneOf : public std::true_type {}; + template + struct TIsOneOf : public TIsOneOf {}; + //! \endcond + /*! * Trait that detects if a type is QPrivateSignal. */