Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何处理c+中的单位+;接口_C++ - Fatal编程技术网

C++ 如何处理c+中的单位+;接口

C++ 如何处理c+中的单位+;接口,c++,C++,我目前正在设计一个API,希望用户能够编写如下代码: PowerMeter.forceVoltage(1 mV); PowerMeter.settlingTime(1 ms); PowerMeter pm; pm.ForceVoltage<MILI_VOLT>(1); pm.ForceVoltage<VOLT>(1); pm.ForceVoltage<KILO_VOLT>(1); 目前,我们使

我目前正在设计一个API,希望用户能够编写如下代码:

PowerMeter.forceVoltage(1 mV);
PowerMeter.settlingTime(1 ms);
        PowerMeter pm;
        pm.ForceVoltage<MILI_VOLT>(1);
        pm.ForceVoltage<VOLT>(1);
        pm.ForceVoltage<KILO_VOLT>(1);
目前,我们使用以下定义进行此操作:

#define mV *1.0e-03
这使得用户编写代码非常方便,可读性也非常好,但当然也有缺点:

int ms;
将抛出一些难以理解的编译器错误。因此,我正在寻找更好的解决方案

我尝试了新的C++11文本,但通过这些,我所能实现的是:

long double operator "" _mV(long double value) {
  return value * 1e-3;
}
PowerMeter.forceVoltage(1_mV);
最后,API不关心单位,如伏特或秒,但只采取了数字,所以我不想做任何检查,如果你真的输入电压电压或没有伏特。因此,这也应该是可能的:

PowerMeter.forceVoltage(2 ms);

除了使用定义之外,你还有什么想法吗?

你可以使用C++11对单位的支持,而不是为单位定义文字或宏。

不如通过为不同的单位创建类(ms,mV)来扭转局面

e、 g

它对用户来说是非常清楚的,并且可以说不难阅读,而且你可以免费获得类型检查。为不同的单元提供一个公共基类将使其更易于实现。

您可以看到Calum Grant中的库“”是如何实现这一点的一个很好的示例。这个图书馆有点过时了,但仍然值得一看或使用

此外,我认为读到以下内容可能会很有趣:

还有一个很好的图书馆:

包含用于物理量单位的C库以及单位定义和值转换实用程序


考虑为您的单位使用
enum
,并将其作为第二个参数传递:

namespace Units
{
    enum Voltage
    {
        millivolts = -3,
        volts = 0,
        kilovolts = 3
    };

    enum Time
    {
        microseconds = -6,
        milliseconds = -3,
        seconds = 0
    };
}

class PowerMeter
{
public:
    void forceVoltage(float baseValue, Units::Voltage unit)
    {
         float value = baseValue * std::pow(10, unit);
         std::cout << "Voltage forced to " << value << " Volts\n";
    }

    void settlingTime(float baseValue, Units::Time unit)
    {
         float value = baseValue * std::pow(10, unit);
         std::cout << "Settling time set to " << value << " seconds\n";
    }
}

int main()
{
    using namespace Units;
    PowerMeter meter;
    meter.settlingTime(1.2, seconds);
    meter.forceVoltage(666, kilovolts);
    meter.forceVoltage(3.4, milliseconds); // Compiler Error
}
名称空间单元
{
枚举电压
{
毫伏=-3,
伏特=0,
千伏=3
};
枚举时间
{
微秒=-6,
毫秒=-3,
秒=0
};
}
类功率计
{
公众:
无效力电压(浮动基准值,单位::电压单位)
{
浮动值=基准值*标准::功率(10,单位);

std::cout以下是我的想法……与Anders K的想法几乎相同,但由于我编写了代码,我将发布它:

#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;
}
#包括
使用名称空间std;
类毫伏值;
类电压值;
类电压值
{
公众:
显式电压值(浮点v=0.0f):\u伏(v){/*空*/}
电压值(恒定毫伏值和mV);
运算符float()常量{return\u volts;}
私人:
浮动电压;
};
类毫伏值
{
公众:
显式毫伏值(浮点mV=0.0f):\u毫伏(mV){/*空*/}
毫伏值(恒伏值&v):_毫伏(v*1000.0f){/*empty*/}
运算符float()常量{return\u毫伏;}
私人:
浮动毫伏;
};
伏特值:伏特值(常量毫伏值和毫伏值):_伏特(毫伏/1000.0f){/*空*/}
类功率计
{
公众:
功率计(){/*空*/}
无效电压(常数电压值&v){u电压值=v;}
VoltsValue getVoltage()常量{return\u VoltsValue;}
私人:
伏特值_伏特值;
};
int main(int argc,字符**argv)
{
功率计;
仪表力电压(电压值(5.0f));

cout我更喜欢Anders K的解决方案,但是您可以使用一个模板来节省一些时间,将所有单元实现为一个separte类,这可能非常耗时,并且容易出错,因为您可能需要手工编写大量代码:

enum Unit {
    MILI_VOLT = -3,
    VOLT = 0,
    KILO_VOLT = 3
};

class PowerMeter
{
public:

    template<int N>
    void ForceVoltage(double val)
    {
        std::cout << val * pow(10.0, N) << endl;
    };
};
枚举单元{
毫伏=-3,
电压=0,
千伏=3
};
类功率计
{
公众:
模板
真空力电压(双val)
{

std::cout我更喜欢尽可能避免使用宏,这是一个可能的例子。 为您提供正确尺寸的一个轻量级解决方案是:

static double m = 1;
static double cm = 0.1;
static double mV = 0.001;

double distance = 10*m + 10*cm;
这也反映了物理概念,即单位是与值相乘的东西。

看看。 下面是一些示例代码:

quantity<energy>
work(const quantity<force>& F, const quantity<length>& dx)
{
    return F * dx; // Defines the relation: work = force * distance.
}

...

/// Test calculation of work.
quantity<force>     F(2.0 * newton); // Define a quantity of force.
quantity<length>    dx(2.0 * meter); // and a distance,
quantity<energy>    E(work(F,dx));  // and calculate the work done.
数量
工程(施工数量和F、施工数量和dx)
{
返回F*dx;//定义关系:功=力*距离。
}
...
///功的测试计算。
数量F(2.0*牛顿);//定义力的数量。
数量dx(2.0*米);//和距离,
数量E(功(F,dx));//并计算完成的功。

在你对任何更复杂的事情发狂之前,每当你编写以数量为参数的新代码时,你应该像这样命名你的方法,以便100%清楚:

PowerMeter.forceInMilliVolts( ... )
PowerMeter.settlingTimeInSeconds( ... )
同样,使用具有正确名称的变量,例如:

int seconds(10);
int milliVolts(100);
这样,你是否必须转换并不重要,你正在做的事情仍然很清楚

PowerMeter.settlingTimeInSeconds( minutes*60 );

当你准备好使用更强大的设备时,如果你真的需要的话,可以这样做,但要确保你不丢失正在使用的设备的清晰性。

你能将您的设备作为一个单独的变量传递吗?
PowerMeter.forceVoltage(2,“ms”)但是,这不是用户想要的自然方式。为什么……所以你想指定度量单位,但不想检查它们是否正确?这是没有意义的。此外,你的“用户”知道C++,但关心“自然方式”……几乎是不可想象的。为什么不只是包含它?实际上,大多数用户不是真正的C++程序员。因此,我们希望保持API简单。包括函数名称是difult,因为我们将拥有FraceTrf()FraceIrror(…)。注意,你所做的只是附加SI前缀,而不是单元(MLLI:1E-03不是单位,它是一个值/前缀)。。鉴于OP是如何尝试C++11文字的,
枚举类
会更合适。@chris:使用
枚举类
,无法使用
指令将当前范围内的所有单元名称都拉入
。因此,您必须在每个单元前加前缀(例如
电压::伏特
)是的。我想这取决于用户想要写什么样的代码。+1除比率外,维度是最重要的部分。维度确定后,老鼠
PowerMeter.settlingTimeInSeconds( minutes*60 );