From 07e64099b1573a15768994555720bcf11112ae69 Mon Sep 17 00:00:00 2001 From: Mat Sutcliffe Date: Wed, 25 Sep 2019 21:11:19 +0100 Subject: [PATCH] Ref T725 Extend CLogMessage to allow ICoordinateGeodetic arguments, using a system of traits to select the stringifier corresponding to the argument type. --- src/blackmisc/geo/coordinategeodetic.h | 12 +++- src/blackmisc/statusmessage.h | 21 ++---- src/blackmisc/stringutils.h | 97 ++++++++++++++++++++++++++ src/blackmisc/typetraits.h | 19 +++++ 4 files changed, 130 insertions(+), 19 deletions(-) diff --git a/src/blackmisc/geo/coordinategeodetic.h b/src/blackmisc/geo/coordinategeodetic.h index 307066dc9..e312355b4 100644 --- a/src/blackmisc/geo/coordinategeodetic.h +++ b/src/blackmisc/geo/coordinategeodetic.h @@ -20,6 +20,7 @@ #include "blackmisc/math/mathutils.h" #include "blackmisc/metaclass.h" #include "blackmisc/propertyindex.h" +#include "blackmisc/stringutils.h" #include "blackmisc/valueobject.h" #include "blackmisc/variant.h" #include "blackmisc/blackmiscexport.h" @@ -135,9 +136,6 @@ namespace BlackMisc //! \copydoc Mixin::String::toQString QString convertToQString(bool i18n = false) const; - //! \copydoc Mixin::String::toQString - // QString toQString(bool i18n = false) const { return this->convertToQString(i18n); } - //! Check values @{ bool isNaNVector() const; bool isNaNVectorDouble() const; @@ -353,6 +351,14 @@ namespace BlackMisc ); }; } // namespace + + //! \cond + template <> + struct TString + { + static QString toQString(const Geo::ICoordinateGeodetic &coord) { return coord.convertToQString(); } + }; + //! \endcond } // namespace Q_DECLARE_METATYPE(BlackMisc::Geo::CCoordinateGeodetic) diff --git a/src/blackmisc/statusmessage.h b/src/blackmisc/statusmessage.h index d430ef357..f5df51ae6 100644 --- a/src/blackmisc/statusmessage.h +++ b/src/blackmisc/statusmessage.h @@ -16,6 +16,7 @@ #include "orderable.h" #include "icon.h" #include "propertyindex.h" +#include "stringutils.h" #include "typetraits.h" #include "blackmiscexport.h" @@ -234,22 +235,10 @@ namespace BlackMisc //! Otherwise, the streamed values will replace the place markers %1, %2, %3... in the format string. //! \see QString::arg //! @{ - Derived &operator <<(const QString &v) { return arg(v); } - Derived &operator <<(const QStringRef &v) { return arg(v.toString()); } - Derived &operator <<(QStringView v) { return arg(v.toString()); } - Derived &operator <<(int v) { return arg(QString::number(v)); } - Derived &operator <<(uint v) { return arg(QString::number(v)); } - Derived &operator <<(long v) { return arg(QString::number(v)); } - Derived &operator <<(ulong v) { return arg(QString::number(v)); } - Derived &operator <<(qlonglong v) { return arg(QString::number(v)); } - Derived &operator <<(qulonglong v) { return arg(QString::number(v)); } - Derived &operator <<(short v) { return arg(QString::number(v)); } - Derived &operator <<(ushort v) { return arg(QString::number(v)); } - Derived &operator <<(QChar v) { return arg(v); } - Derived &operator <<(char v) { return arg(QChar(v)); } - Derived &operator <<(double v) { return arg(QString::number(v)); } - template ::value>> - Derived & operator <<(const T &v) { return arg(v.toQString()); } + template >::passBy == ParameterPassBy::Value, int> = 0> + Derived &operator <<(T v) { return arg(TString::toQString(v)); } + template >::passBy == ParameterPassBy::ConstRef, int> = 0> + Derived &operator <<(const T &v) { return arg(TString::toQString(v)); } //! @} //! Message empty diff --git a/src/blackmisc/stringutils.h b/src/blackmisc/stringutils.h index dbdbec302..c82847662 100644 --- a/src/blackmisc/stringutils.h +++ b/src/blackmisc/stringutils.h @@ -13,19 +13,23 @@ #include "blackmisc/blackmiscexport.h" #include "blackmisc/range.h" +#include "blackmisc/typetraits.h" #include #include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -372,6 +376,99 @@ namespace BlackMisc using ::BlackMisc::Mixin::String::stringForStreaming; // *INDENT-ON* } // ns + + /*! + * Stringification traits class. + */ + template struct TString; + + // Stringification traits specializations. + //! \cond + template <> struct TString + { + static QString toQString(const QString &s) { return s; } + }; + template <> struct TString + { + static QString toQString(const QStringRef &sr) { return sr.toString(); } + }; + template <> struct TString + { + static QString toQString(QStringView sv) { return sv.toString(); } + }; + template <> struct TString + { + static QString toQString(QChar c) { return c; } + }; + template <> struct TString + { + static QString toQString(char c) { return QChar(c); } + }; + template <> struct TString + { + static QString toQString(bool n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(int n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(uint n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(long n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(ulong n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(qlonglong n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(qulonglong n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(short n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(ushort n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(float n) { return QString::number(n); } + }; + template <> struct TString + { + static QString toQString(double n) { return QString::number(n); } + }; + template struct TString::value>> + { + static QString toQString(T e) { return QString::number(e); } + }; + template struct TString::value>> + { + static QString toQString(const T &v) { return v; } + }; + template struct TString::value>> + { + static QString toQString(const T &v) { return v.toQString(); } + }; + template struct TString> + { + static QString toQString(QFlags n) { return TString::Int>::toQString(n); } + }; + template struct TString> + { + static QString toQString(const std::atomic &n) { return TString::toQString(n); } + }; + //! \endcond } // ns #endif // guard diff --git a/src/blackmisc/typetraits.h b/src/blackmisc/typetraits.h index e2e124489..1ef431926 100644 --- a/src/blackmisc/typetraits.h +++ b/src/blackmisc/typetraits.h @@ -52,6 +52,25 @@ namespace BlackMisc //! \endcond } + /*! + * Whether an input parameter type should be passed by value or by const reference. + */ + enum class ParameterPassBy + { + Value, + ConstRef + }; + + /*! + * Trait to detect properties of function parameter types. + */ + template + struct TParameter + { + //! Whether the input parameter type T should be passed by value or by const reference. + static constexpr ParameterPassBy passBy = (sizeof(T) <= 16 && std::is_trivially_copy_constructible::value && std::is_trivially_destructible::value) ? ParameterPassBy::Value : ParameterPassBy::ConstRef; + }; + /*! * Trait to detect whether T contains a member function toQString. */