How to handle units in c++ interface

前端 未结 9 2120
独厮守ぢ
独厮守ぢ 2021-02-07 02:56

I am currently designing an API where I want that the user to be able to write code like this:

PowerMeter.forceVoltage(1 mV);
PowerMeter.settlingTime(1 ms);


        
相关标签:
9条回答
  • 2021-02-07 03:37

    Here's what I came up with... pretty much the same idea as Anders K, but since I wrote the code, I'll post it:

    #include <iostream>
    
    using namespace std;
    
    class MilliVoltsValue;
    class VoltsValue;
    
    class VoltsValue
    {
    public:
       explicit VoltsValue(float v = 0.0f) : _volts(v) {/* empty */}
       VoltsValue(const MilliVoltsValue & mV);
    
       operator float() const {return _volts;}
    
    private:
       float _volts;
    };
    
    class MilliVoltsValue
    {
    public:
       explicit MilliVoltsValue(float mV = 0.0f) : _milliVolts(mV) {/* empty */}
       MilliVoltsValue(const VoltsValue & v) : _milliVolts(v*1000.0f) {/* empty */}
    
       operator float() const {return _milliVolts;}
    
    private:
       float _milliVolts;
    };
    
    VoltsValue :: VoltsValue(const MilliVoltsValue & mV) : _volts(mV/1000.0f) {/* empty */}
    
    class PowerMeter
    {
    public:
       PowerMeter() {/* empty */}
    
       void forceVoltage(const VoltsValue & v) {_voltsValue = v;}
       VoltsValue getVoltage() const {return _voltsValue;}
    
    private:
       VoltsValue _voltsValue;
    };
    
    int main(int argc, char ** argv)
    {
       PowerMeter meter;
    
       meter.forceVoltage(VoltsValue(5.0f));
       cout << "Current PowerMeter voltage is " << meter.getVoltage() << " volts!" << endl;
    
       meter.forceVoltage(MilliVoltsValue(2500.0f));
       cout << "Now PowerMeter voltage is " << meter.getVoltage() << " volts!" << endl;
    
       // The line below will give a compile error, because units aren't specified
       meter.forceVoltage(3.0f);   // error!
    
       return 0;
    }
    
    0 讨论(0)
  • 2021-02-07 03:42

    how about instead turning it around a bit by creating classes (ms,mV) for the different currents

    e.g.

    PowerMeter.forceVoltage( mV(1) );  
    PowerMeter.settlingTime( ms(1) )
    

    It is pretty clear to the user and arguably not hard to read plus you would get type checking for free. having a common base class for the different units would make it easier to implement.

    0 讨论(0)
  • 2021-02-07 03:43

    You can see the library "C++ Units" from Calum Grant as a good example of how to implement this. The library is a bit outdated, but still worth to see or may be to use.

    Also, i think it might be interesting to read: "Applied Template Metaprogramming in SI UNITS: the Library of Unit-Based Computation"

    There is one more good library: UDUNITS-2 which:

    contains a C library for units of physical quantities and a unit-definition and value-conversion utility.

    0 讨论(0)
提交回复
热议问题