#include #include #include #include #include #include #include #include #include //----------------------------------------------------------------------------- // This class describes characteristics a double parameter has //----------------------------------------------------------------------------- class TCDoubleTraits { public: TCDoubleTraits( const std::string& Label, const std::string& UiUnits = std::string(), const boost::optional& UiDigitsAfterDecimal = boost::optional(), double InternalToUiScale = 1); std::string mLabel; std::string mUiUnits; boost::optional mUiDigitsAfterDecimal; double mInternalToUiScale; std::string GetString( double Value, bool WithLabel, bool WithUnits) const; private: std::string GetDoubleAsString(double Value) const; }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- std::string TCDoubleTraits::GetString( double Value, bool WithLabel, bool WithUnits) const { std::string Return; if (WithLabel) { Return = mLabel; Return.append(" = "); } Return.append(GetDoubleAsString(Value)); if (WithUnits && !mUiUnits.empty()) { Return.append(" ("); Return.append(mUiUnits); Return.append(")"); } return Return; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- std::string TCDoubleTraits::GetDoubleAsString(double Value) const { if (Value != Value) { return "NaN"; } std::ostringstream Stream; if (mUiDigitsAfterDecimal) { Stream << std::fixed << std::setprecision(*mUiDigitsAfterDecimal); } Stream << Value * mInternalToUiScale; return Stream.str(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- TCDoubleTraits::TCDoubleTraits( const std::string& Label, const std::string& UiUnits, const boost::optional& UiDigitsAfterDecimal, double InternalToUiScale) : mLabel(Label), mUiUnits(UiUnits), mUiDigitsAfterDecimal(UiDigitsAfterDecimal), mInternalToUiScale(InternalToUiScale) { } //----------------------------------------------------------------------------- // This class describes characteristics an unsigned parameter has //----------------------------------------------------------------------------- class TCUnsignedTraits { public: TCUnsignedTraits( const std::string& Label, const std::string& UiUnits = std::string()); std::string mLabel; std::string mUiUnits; std::string GetString( unsigned Value, bool WithLabel, bool WithUnits) const { std::ostringstream Stream; if (WithLabel) { Stream << mLabel << " = "; } Stream << Value; if (WithUnits && !mUiUnits.empty()) { Stream << " (" << mUiUnits << ")"; } return Stream.str(); } }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- TCUnsignedTraits::TCUnsignedTraits( const std::string& Label, const std::string& UiUnits) : mLabel(Label), mUiUnits(UiUnits) { } //----------------------------------------------------------------------------- // This class defines a "position". For each parameter, the "traits" are // provided. //----------------------------------------------------------------------------- class TCPosition { public: double mLatitude; static const TCDoubleTraits sLatitudeTraits; double mAltitude; static const TCDoubleTraits sAltitudeTraits; unsigned mSteps; static const TCUnsignedTraits sStepsTraits; }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- static const double Pi = 3.14159265358979; const TCDoubleTraits TCPosition::sLatitudeTraits( "Latitude", "deg", 5, 180/Pi); const TCDoubleTraits TCPosition::sAltitudeTraits( "Altitude", "m MSL"); const TCUnsignedTraits TCPosition::sStepsTraits("Steps"); //----------------------------------------------------------------------------- // This class holds the traits for a "position" object. It provides a // machanism to write out each of the parameters of a position, provided // you can provide a pointer to a position. The order the values are // printed is defined at compile time in the mItems member. //----------------------------------------------------------------------------- class TCPositionTraits { public: static void PrintValues( const TCPosition* pPosition, bool WithLabel, bool WithUnits); private: //------------------------------------------------------------------------- //------------------------------------------------------------------------- struct TSItem { virtual ~TSItem() {} virtual void PrintValue( const TCPosition* pPosition, const bool WithLabel, const bool WithUnits) const = 0; }; //------------------------------------------------------------------------- //------------------------------------------------------------------------- struct TSItemDouble : public TSItem { TSItemDouble( const TCDoubleTraits* pDoubleTraits, boost::function GetDouble); void PrintValue( const TCPosition* pPosition, const bool WithLabel, const bool WithUnits) const; const TCDoubleTraits* mpDoubleTraits; boost::function mGetDouble; }; //------------------------------------------------------------------------- //------------------------------------------------------------------------- struct TSItemUnsigned : public TSItem { TSItemUnsigned( const TCUnsignedTraits* pUnsignedTraits, boost::function GetUnsigned); void PrintValue( const TCPosition* pPosition, const bool WithLabel, const bool WithUnits) const; const TCUnsignedTraits* mpUnsignedTraits; boost::function mGetUnsigned; }; static const std::vector > mItems; }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- TCPositionTraits::TSItemDouble::TSItemDouble( const TCDoubleTraits* pDoubleTraits, boost::function GetDouble) : mpDoubleTraits(pDoubleTraits), mGetDouble(GetDouble) { } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void TCPositionTraits::TSItemDouble::PrintValue( const TCPosition* pPosition, const bool WithLabel, const bool WithUnits) const { std::cout << mpDoubleTraits->GetString( mGetDouble(pPosition), WithLabel, WithUnits) << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- TCPositionTraits::TSItemUnsigned::TSItemUnsigned( const TCUnsignedTraits* pUnsignedTraits, boost::function GetUnsigned) : mpUnsignedTraits(pUnsignedTraits), mGetUnsigned(GetUnsigned) { } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void TCPositionTraits::TSItemUnsigned::PrintValue( const TCPosition* pPosition, const bool WithLabel, const bool WithUnits) const { std::cout << mpUnsignedTraits->GetString( mGetUnsigned(pPosition), WithLabel, WithUnits) << std::endl; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- const std::vector > TCPositionTraits::mItems = { boost::make_shared( &TCPosition::sLatitudeTraits, boost::bind(&TCPosition::mLatitude, _1)), boost::make_shared( &TCPosition::sAltitudeTraits, boost::bind(&TCPosition::mAltitude, _1)), boost::make_shared( &TCPosition::sStepsTraits, boost::bind(&TCPosition::mSteps, _1)) }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void TCPositionTraits::PrintValues( const TCPosition* pPosition, bool WithLabel, bool WithUnits) { for (const auto& pItem : mItems) { pItem->PrintValue(pPosition, WithLabel, WithUnits); } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- int main() { TCPosition Position; Position.mLatitude = 0.2; Position.mAltitude = 321; Position.mSteps = 4; TCPositionTraits::PrintValues(&Position, true, true); return 0; }