在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&){...}
Time
,Length
和Speed
只能作为来自不同运营商的返回类型创建?
答案 0 :(得分:53)
在C ++中是否能够将物理单位定义为单独的类型并在这些类型之间定义有效的操作?
绝对。标准的Chrono库已经针对时间点和持续时间执行此操作。
引入很多类型和大量的运算符重载是否有任何优势,而不是仅使用普通的浮点值来表示它们?
是:您可以使用类型系统来捕获错误,例如在编译时将质量添加到距离,而不会增加任何运行时开销。
如果您不想自己定义类型和运算符,Boost会为此设置Units library。
答案 1 :(得分: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
答案 2 :(得分:13)
我走了这条路。优点是类型安全的正常数量和良好优势。我遇到的缺点:
velocity
的类型)。在一天结束时,它非常干净,简单的计算和简单的目的。但是当数学变得复杂时,很难让打字的单位系统发挥得很好。
答案 3 :(得分: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.";
该类的用户不需要知道内部表示使用的单位......至少,只要没有严重的舍入问题。
我真的希望更多的三角函数库可以用角度来做这个,因为我总是要查看它们是否期望度数或弧度...
答案 4 :(得分:4)
对于那些寻找强大的编译时类型安全单元库的人,但是对于拖动boost依赖性犹豫不决,请查看units。该库是作为单个.h文件实现的,没有依赖项,并附带了一个构建单元测试/文档的项目。它已经使用msvc2013,2015和gcc-4.9.2进行了测试,并且也应该与这些编译器的更高版本一起使用。
完全披露:我是图书馆的作者
答案 5 :(得分:1)
是的,这很有道理。不仅在物理学,而且在任何学科。在金融领域,例如利率以反时间间隔为单位(通常每年表示)。钱有很多不同的单位。它们之间的转换只能通过交叉汇率进行,一种货币的维度除以另一种货币。利息支付,股息支付,本金支付等通常会频繁发生。
它可以防止乘以两个值并最终得到非法值。它可以防止汇总美元和欧元等。
答案 6 :(得分:1)
我并不是说你这样做是错的,但是我们在我正在进行的项目中已经过分了,坦率地说,我怀疑它的好处超过了它的麻烦。特别是如果你是一个团队,那么良好的变量命名(只是拼写出来的东西),代码审查和单元测试都可以防止出现任何问题。另一方面,如果你可以使用Boost,可能需要检查单位(我还没有)。
答案 7 :(得分:1)
要检查类型安全性,您可以使用专用库。
最令人厌恶的用途是boost :: units,它完美地工作,没有执行时间开销,很多功能。如果这个库理论上解决了你的问题。从一个更实用的角度来看,界面非常笨拙且记录严重,以至于您可能遇到问题。更多的编译时间随着维度的数量而急剧增加,因此请在使用之前清楚地检查您是否可以在合理的时间内编译大型项目。
doc:http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
另一种方法是使用unit_lite。功能少于boost库,但编译速度更快,界面更简单,错误消息也是可读的。这个lib需要C ++ 11。
代码:https://github.com/pierreblavy2/unit_lite
doc的链接在github描述中(我不允许在这里发布超过2个链接!!!)。
答案 8 :(得分:1)
我在Boost.Units库的CPPcon 2015上做了一个教程演示。它是一个功能强大的库,每个科学应用程序都应该使用它。但由于文档很差,很难使用它。希望我的教程有助于此。您可以找到幻灯片/代码here: