From 48482d8d1ea87602899d59a72d5edca48c4dc7bb Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 21 Apr 2017 02:06:03 +0100 Subject: [PATCH] T73 CMeasurementUnit converter strategy based on function pointers. Because function pointers are literal types, so they can be constexpr. --- src/blackmisc/pq/measurementunit.cpp | 4 +- src/blackmisc/pq/measurementunit.h | 66 ++++++++++++---------------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/blackmisc/pq/measurementunit.cpp b/src/blackmisc/pq/measurementunit.cpp index aa0fa3907..810124ffe 100644 --- a/src/blackmisc/pq/measurementunit.cpp +++ b/src/blackmisc/pq/measurementunit.cpp @@ -32,8 +32,8 @@ namespace BlackMisc double CMeasurementUnit::convertFrom(double value, const CMeasurementUnit &unit) const { if (this->isNull() || unit.isNull()) return 0; - if (this->m_converter == unit.m_converter) return value; - return this->m_converter->fromDefault(unit.m_converter->toDefault(value)); + if (this->m_toDefault == unit.m_toDefault && this->m_fromDefault == unit.m_fromDefault) return value; + return this->m_fromDefault(unit.m_toDefault(value)); } QString CMeasurementUnit::makeRoundedQStringWithUnit(double value, int digits, bool i18n) const diff --git a/src/blackmisc/pq/measurementunit.h b/src/blackmisc/pq/measurementunit.h index 32043fb95..0b54652f7 100644 --- a/src/blackmisc/pq/measurementunit.h +++ b/src/blackmisc/pq/measurementunit.h @@ -46,41 +46,26 @@ namespace BlackMisc { protected: /*! - * Abstract strategy pattern that encapsulates a unit conversion strategy. + * Pointer to function for converting between units. */ - class Converter : public QSharedData - { - public: - /*! - * Virtual destructor. - */ - virtual ~Converter() {} - /*! - * Convert from this unit to default unit. - */ - virtual double toDefault(double value) const = 0; - /*! - * Convert from default unit to this unit. - */ - virtual double fromDefault(double value) const = 0; - }; + using ConverterFunction = double (*)(double); /*! * Converter for default values, such as None, used with public constructor */ - struct NilConverter : public Converter + struct NilConverter { - virtual double toDefault(double) const override { return 0.0; } - virtual double fromDefault(double) const override { return 0.0; } + static double toDefault(double) { return 0.0; } //!< convert from this unit to the default unit + static double fromDefault(double) { return 0.0; } //!< convert to this unit from the default unit }; /*! * Concrete strategy pattern for converting unit that does nothing. */ - struct IdentityConverter : public Converter + struct IdentityConverter { - virtual double toDefault(double value) const override { return value; } - virtual double fromDefault(double value) const override { return value; } + static double toDefault(double value) { return value; } //!< convert from this unit to the default unit + static double fromDefault(double value) { return value; } //!< convert to this unit from the default unit }; /*! @@ -88,10 +73,10 @@ namespace BlackMisc * \tparam Policy a policy class with static method factor() returning double */ template - struct LinearConverter : public Converter + struct LinearConverter { - virtual double toDefault(double value) const override { return value * Policy::factor(); } - virtual double fromDefault(double value) const override { return value / Policy::factor(); } + static double toDefault(double value) { return value * Policy::factor(); } //!< convert from this unit to the default unit + static double fromDefault(double value) { return value / Policy::factor(); } //!< convert to this unit from the default unit }; /*! @@ -99,10 +84,10 @@ namespace BlackMisc * \tparam Policy a policy class with static methods factor() and offset() returning double */ template - struct AffineConverter : public Converter + struct AffineConverter { - virtual double toDefault(double value) const override { return (value - Policy::offset()) * Policy::factor(); } - virtual double fromDefault(double value) const override { return value / Policy::factor() + Policy::offset(); } + static double toDefault(double value) { return (value - Policy::offset()) * Policy::factor(); } //!< convert from this unit to the default unit + static double fromDefault(double value) { return value / Policy::factor() + Policy::offset(); } //!< convert to this unit from the default unit }; /*! @@ -111,16 +96,18 @@ namespace BlackMisc * \tparam SubdivPolicy a policy class with static methods fraction() and subfactor() returning double */ template - struct SubdivisionConverter : public Converter + struct SubdivisionConverter { - virtual double toDefault(double value) const override + //! convert from this unit to the default unit + static double toDefault(double value) { using BlackMisc::Math::CMathUtils; double part2 = CMathUtils::fract(value) * SubdivPolicy::fraction(); value = CMathUtils::trunc(value) + part2 / SubdivPolicy::subfactor(); return value * FactorPolicy::factor(); } - virtual double fromDefault(double value) const override + //! convert to this unit from the default unit + static double fromDefault(double value) { using BlackMisc::Math::CMathUtils; double part1 = CMathUtils::trunc(value / FactorPolicy::factor()); @@ -136,9 +123,10 @@ namespace BlackMisc * \tparam SubdivPolicy a policy class with static methods fraction() and subfactor() returning double */ template - struct SubdivisionConverter2 : public Converter + struct SubdivisionConverter2 { - virtual double toDefault(double value) const override + //! convert from this unit to the default unit + static double toDefault(double value) { using BlackMisc::Math::CMathUtils; double part2 = CMathUtils::fract(value) * SubdivPolicy::fraction(); @@ -146,7 +134,8 @@ namespace BlackMisc value = CMathUtils::trunc(value) + (CMathUtils::trunc(part2) + part3 / SubdivPolicy::subfactor()) / SubdivPolicy::subfactor(); return value * FactorPolicy::factor(); } - virtual double fromDefault(double value) const override + //! convert to this unit from the default unit + static double fromDefault(double value) { using BlackMisc::Math::CMathUtils; double part1 = CMathUtils::trunc(value / FactorPolicy::factor()); @@ -220,7 +209,8 @@ namespace BlackMisc QString m_symbol; //!< unit name, e.g. "m" double m_epsilon; //!< values with differences below epsilon are the equal int m_displayDigits; //!< standard rounding for string conversions - QSharedDataPointer m_converter; //!< strategy pattern allows an arbitrary conversion method as per object + ConverterFunction m_toDefault = nullptr; //!< convert from this unit to default unit + ConverterFunction m_fromDefault = nullptr; //!< convert to this unit from default unit protected: /*! @@ -228,7 +218,7 @@ namespace BlackMisc */ template CMeasurementUnit(const QString &name, const QString &symbol, const Converter &, int displayDigits, double epsilon) - : m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_converter(new Converter) + : m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_toDefault(Converter::toDefault), m_fromDefault(Converter::fromDefault) {} /*! @@ -326,7 +316,7 @@ namespace BlackMisc //! Is unit null? bool isNull() const { - return this->m_converter.data() == nullptr; + return this->m_toDefault == nullptr; } // --------------------------------------------------------------------