C++中的度量单位

w80xi6nr  于 2023-02-10  发布在  其他
关注(0)|答案(4)|浏览(133)

我正在开发一个游戏引擎,目前我还在设计IO系统。我已经做到了,引擎本身不处理任何文件格式,而是让用户通过创建一个*.dll文件,其中包含适当命名的函数来实现任何他想要的东西。虽然这本身不是什么大问题,我主要关心的是在引擎使用过程中可能会看到的暗示。
我设计了一个简单的resource接口,作为用户能想到的所有东西的基类,我试图通过创建专用于常见数据类型的简单子类来扩展它,这样用户就不必自己实现基本的东西(目前我想到的是audioimagedatamesh),从audio类开始,我偶然发现了一个奇怪的问题,当我试图决定我应该用什么类型存储关于采样率的信息时。通常的单位是赫兹,所以我决定把它设为unsigned int
但是这里有一个小问题--如果用户试图将其设置为千赫怎么办?让我们假设一些抽象文件格式可以暂时将其存储为两种单位。我创建了一个简单的 Package 器类来命名单位类型:

class hertz{
private:
    unsigned int value;
    hertz(){};
public:
    operator unsigned int();
    hertz(unsigned int value);
};

并决定让用户也使用kHz:

class kilohertz{
private:
    float value;
    kilohertz(){};
public:
    operator hertz();
    kilohertz(float value);
};

audio类中的函数允许用户设置采样率,它被声明为track& samplingRate(units::hertz rate);,用户必须通过显式说明使用的数量级来调用它:

someAudioFile.samplingRate(hertz(44100));
someAudioFile.samplingRate(kilohertz(44.1));

我的问题是:
有没有更好的方法来迫使用户以简单而优雅的方式使用度量单位?也许是设计模式,或者是typedefs的巧妙使用?
还请注意,在创建引擎的过程中,我可能需要更多的单位,这将是不兼容的赫兹。从我的头顶-我可能希望用户能够设置一个像素的颜色都做units::rgb(123,42,120)units::hsl(10,30,240)
我试着寻找一个可行的答案,只找到了this question,但OP只想要数量级,而没有确保这些单元与其他单元不兼容。
另外请注意,我使用的是旧的C++版本,而不是C++11。虽然发布一个在任何版本中有效的解决方案都很好,但如果我也能使用它就更好了:)

3bygqnnd

3bygqnnd1#

我知道您提到过您没有使用C11,但其他人可能会看到这个问题,所以下面是使用用户定义的文本的C11解决方案:
http://ideone.com/UzeafE

#include <iostream>
using namespace std;

class Frequency
{
public:
    void Print() const { cout << hertz << "Hz\n"; }

    explicit constexpr Frequency(unsigned int h) : hertz(h) {}
private:
    unsigned int hertz;
};
constexpr Frequency operator"" _Hz(unsigned long long hz)
{
    return Frequency{hz};
}
constexpr Frequency operator"" _kHz(long double khz)
{
    return Frequency{khz * 1000};
}

int main()
{
    Frequency(44100_Hz).Print();
    Frequency(44.1_kHz).Print();
    return 0;
}

输出:

44100Hz
44100Hz
0g0grzrc

0g0grzrc3#

你可以使用factory design pattern来完成你所寻找的。你可以创建一个频率类,它有一个私有的构造函数和几个静态方法,这些方法将根据用户想要使用的单位来构造对象。通过保持构造函数私有,用户被迫显式地声明他的单位,这减少了用户出错的可能性。

#include <iostream>

using namespace std;

class frequency
{
public:
  static frequency hertz(int hz)
  {
    return frequency(hz);
  }

  static frequency kilohertz(double kHz)
  {
    return frequency(kHz * KHZ_TO_HZ);
  }

  static frequency rpm(int rpm)
  {
    return frequency(rpm * RPM_TO_HZ);
  }

  int hz()
  {
    return m_hz;
  }

private:
  static const int KHZ_TO_HZ = 1000;
  static const int RPM_TO_HZ = 60;

  frequency(int hz) : m_hz(hz)
  {
  }

  int m_hz;
};

int main()
{
  wcout << frequency::hertz(44100).hz() << "Hz" << endl;
  wcout << frequency::kilohertz(44.100).hz() << "Hz" << endl;
}
qlfbtfca

qlfbtfca4#

2023年更新

如果至少使用C++14gcc >=5.4.0,则可以使用此库
https://github.com/nholthaus/units
也可以使用 * Conan软件包管理器 * 进行安装
https://conan.io/center/units?os=&tab=overview.

相关问题