C ++中的度量单位

时间:2014-02-19 00:14:00

标签: c++ design-patterns units-of-measurement

我正在开发一款游戏引擎,目前我一直在设计IO系统。我已经做到了,引擎本身并不处理任何文件格式,而是让用户通过在内部创建具有适当命名函数的*.dll文件来实现他想要的任何内容。虽然这本身并不是什么问题,但我主要担心的是在发动机使用过程中可能会出现的影响。

我设计了一个简单的resource接口作为用户可以想到的所有内容的基类,我试图通过创建专用于公共数据类型的简单子类来扩展它,因此用户不需要自己实现基础知识(目前我正在考虑audioimagedatamesh)。从audio课开始,我偶然发现了一个特殊的问题,同时试图决定应该以什么类型存储有关采样率的信息。通常的单位是赫兹,所以我决定将其设为unsigned int

但是这里有一点问题 - 如果用户试图将其设置为千赫兹怎么办?让我们假设一些抽象文件格式可以暂时将它存储在两个单元中。我已经创建了一个简单的包装类来命名单元类型:

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));

我的问题是:

  

有没有更好的方法强制用户以简单而优雅的方式使用测量单位?一个设计模式可能,或者巧妙地使用typedef?

请注意,在创建引擎的过程中,我可能需要更多与Hertz不兼容的单元。从我的头脑中 - 我可能希望用户能够通过units::rgb(123,42,120)units::hsl(10,30,240)设置像素颜色。

我已经尝试寻找可行的答案并且只找到了this question,但OP只需要数量级而不确保单位与其他单位不兼容。

另请注意,我使用的是旧C++版本,而不是C++11。虽然在任何版本中发布有效的解决方案都很棒,但如果我也可以使用它会很好:)

3 个答案:

答案 0 :(得分:25)

我知道你提到过你没有使用C ++ 11,但是其他人在看这个问题可能是,所以这里是使用用户定义文字的C ++ 11解决方案:

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

答案 1 :(得分:8)

Boost“Units”库非常适合此类事物。

http://www.boost.org/doc/libs/1_55_0/doc/html/boost_units.html

答案 2 :(得分:4)

您可以使用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;
}