在C++中键入安全的物理操作

Mir*_*pas 58 c++ type-safety c++11

在C++中是否能够将物理单位定义为单独的类型并在这些类型之间定义有效的操作?

引入很多类型和大量的运算符重载是否有任何优势,而不是仅使用普通的浮点值来表示它们?

例:

class Time{...};
class Length{...};
class Speed{...};
...
Time operator""_s(long double val){...}
Length operator""_m(long double val){...}
...
Speed operator/(const Length&, const Time&){...}
Run Code Online (Sandbox Code Playgroud)

哪里Time,Length并且Speed只能作为来自不同运营商的返回类型创建?

Mik*_*our 55

在C++中是否能够将物理单位定义为单独的类型并在这些类型之间定义有效的操作?

绝对.标准的Chrono库已经针对时间点和持续时间执行此操作.

引入很多类型和大量的运算符重载是否有任何优势,而不是仅使用普通的浮点值来表示它们?

是的:您可以使用类型系统来捕获错误,例如在编译时将质量添加到距离,而不会增加任何运行时开销.

如果你不想自己定义类型和运算符,Boost有一个Units库.

  • 小修正:你应该使用`boost :: units`(或类似)"如果你不想自己定义类型和操作符,"如你所说,**或**如果你是一个程序员谁不'遭受["未发明在这里"综合症](http://en.wikipedia.org/wiki/Not_invented_here)并意识到[重新发明轮子]的无用性(http://en.wikipedia.org/wiki/Reinventing_the_wheel ).所以基本上,是的,使用它. (4认同)

Vik*_*ehr 21

我真的会为此推荐boost :: units.它完成所有转换编译时间,如果您尝试使用错误的维度伪造代码示例,它也会给您一个编译时错误:

length l1, l2, l3;
area a1 = l1 * l2; // Compiles
area a2 = l1 * l2 * l3; // Compile time error, an area can't be the product of three lengths.
volume v1 = l1 * l2 * l3; // Compiles
Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 13

我走了这条路.优点是类型安全的正常数量和良好优势.我遇到的缺点:

  • 您需要在计算中保存中间值...例如秒平方.将这些值设为类型有点无意义(秒^ 2显然不是类似的类型velocity).
  • 您将需要进行越来越复杂的计算,这将需要越来越多的重载/运算符定义来实现.

在一天结束时,它非常干净,简单的计算和简单的目的.但是当数学变得复杂时,很难让打字的单位系统发挥得很好.

  • #Dave:长度通常是类型为"unit <1,0,0,0,0,0,0>"的typedef,时间为`unit <0,1,0,0,0,0,0> `,速度显然是`unit <1,-1,0,0,0,0,0>`.长度乘以长度只需加法就可以得到`unit <2,0,0,0,0,0,0>`,不需要其他过载. (7认同)
  • 使用`auto`作为中间体解决了这个问题:) (6认同)
  • 像加速度"m/s ^ 2"这样的常数实际上是每秒每秒米,而不是每秒平方米.我也不同意一个具有秒数平方的常数将毫无意义.如果这是该常量的单位,那么以这种方式存储它们.做一个物理问题,你当然应该在你的页面上写中间结果,即使它本身没有意义. (4认同)

Blu*_*eft 10

每个人都提到了类型安全保证.另一个巨大优势是能够从单位(米)中抽象概念(长度).

因此,例如,处理单位时的常见问题是将SI与度量混合.当概念被抽象为类时,这不再是一个问题:

Length width = Length::fromMeters(2.0);
Length height = Length::fromFeet(6.5);
Area area = width * height; //Area is computed correctly!
cout << "The total area is " << area.toInches() << " inches squared.";
Run Code Online (Sandbox Code Playgroud)

只要没有严重的舍入问题,该类的用户不需要知道内部表示使用哪些单元...至少.


我真的希望有更多的三角函数库可以用角度来做这个,因为我总是要查看它们是否期望度数或弧度......

  • @SigTerm:根本不是真的!事实上,恰恰相反:你的班级用户不再需要担心"脚"或"英寸"等实现细节,而是可以专注于更广泛的概念,如"距离"或"角度".这是**经典的例子,当时OOP最有用! (7认同)
  • @AJMansfield:嗯,脚与米并不是真的.在代码中混合公里和厘米同样容易,同样具有灾难性的结果.像这样的API在它开始之前修复了这个问题! (5认同)