1

在阅读时<ratio><chrono>我试图想象一种Length可以防止意外转换错误的类型。

这就是我得到的:

#include <iostream>
#include <ratio>
using namespace std;

template<typename Scale>
struct Length  {
  long long val_;
  Length(long long val) : val_{val} {}
  Length() = default;
  Length(const Length&) = default;
  Length& operator=(const Length&) = default;
  // conversion
  template<typename Scale2>
  Length(const Length<Scale2> &other)
    : val_{ other.val_*(Scale2::num*Scale::den)/(Scale2::den*Scale::num) }
  { }
  // access
  long long value() const { return val_; }
}; 
typedef Length<ratio<1>> m;
typedef Length<kilo> km;
typedef Length<milli> mm;
typedef Length<ratio<1000,1094>> yard;

像这样使用

int main() {
  km len_km = 300;
  mm len_mm = len_km;
  cout << " millimeter:" << len_mm.value() << endl;
  cout << " m:" << m{len_km}.value() << endl;
  cout << " yd:" << yard{len_km}.value() << endl;
}

现在我可以添加所有+*操作来变得非常舒服...... :-)

我想知道:

  • 是否有更容易访问durationtime_point定义的算术设施<chrono>?我可以用那些减少努力Length吗?
  • 编译时常(Scale2::num*Scale::den)/(Scale2::den*Scale::num)量在转换构造函数中似乎很危险(分数/下溢?),但我想不出更好的元编程方式,这里有什么提示吗?
4

2 回答 2

2
  • 是否有更容易访问durationtime_point定义 的 算术设施<chrono>?我可以用那些减少努力Length吗?

对于“混合模式”算术和比较,您可以利用common_type<T1, T2>::type定义返回类型。duration专门common_type成为 Period1 和 Period2 的最大公约数,其中 Period1 和 Period2 是ratio算术或比较运算中涉及的两个 s。你可以像这样使用它:

template <typename Scale1, typename Scale2>
  typename std::common_type<Length<Scale1>, Length<Scale2>>::type
  operator+(Length<Scale1> x, Length<Scale2> y);

ratio不幸的是,您将不得不重新发明如何在编译时获得两个 s 的最大公约数。从 unsigned long long 的编译时 gcd 和 lcm 元函数开始。

嗯...或者您可以将您的专业化建立common_type在已经为duration. 您可以将结果重新duration解释periodLength. 我还没有原型,只是一个想法。

  • 编译时常 (Scale2::num*Scale::den)/(Scale2::den*Scale::num)量在转换构造函数中似乎很危险(分数/下溢?),但我想不出更好的元编程方式,这里有什么提示吗?

同意。 duration处理这个:

template <class Rep2, class Period2>
  constexpr duration(const duration<Rep2, Period2>& d);

备注:此构造函数不应参与重载决议,除非treat_as_floating_point<rep>::value为 true 或两者 ratio_divide<Period2, period>::den均为 1 且treat_as_floating_point<Rep2>::value为 false。[注意:此要求可防止在基于整数的持续时间类型之间转换时出现隐式截断错误。这种结构很容易导致对久期价值的混淆。——尾注]

enable_if即,您需要Length转换构造函数,使其仅在转换准确时才存在(如果您想将长度基于整数类型)。为了准确地进行转换,转换因子(Scale2::num*Scale::den)/(Scale2::den*Scale::num)必须是可计算的,无需除法(除以 1 除外)。你可以用它ratio_divide来为你做这个除法,然后得到的分母必须是 1(为了精确转换)。

enable_if<ratio_divide<Scale2, Scale1>::type::den == 1, ...>

这是一个很棒的学习项目ratio!玩得开心!:-)

于 2011-05-31T12:56:40.037 回答
1

您使用整数类型来表示物理量。这不是人们通常想要的。如果你坚持使用整数类型,至少要按正确的顺序进行乘除,即先所有乘法再除法(比较 100*(255/256) 和 (100*255)/256)。

在相关说明中,请记住,将长度乘以长度得到的是面积,而不是长度。存在考虑到这一点的现实生活库,请参见例如siunits

于 2011-05-31T09:18:25.233 回答