c++ - C++ 中类型的单位

标签 c++ cpp-core-guidelines

C++ Core Guidlines P.1 change_speed 示例,它显示了一个 Speed 类型,使用如下所示:

change_speed(Speed s); // better: the meaning of s is specified
// ...
change_speed(2.3); // error: no unit
change_speed(23m / 10s); // meters per second

我对这个例子的最后两行特别感兴趣。第一个似乎表明,如果您没有为 change_speed 提供参数的单位,它将引发错误。最后一行显示了使用一些 ms 文字定义的单位。现代版本的 C++ 中是否有这两个新特性?如果是这样,如何实现这样的东西,需要什么版本的 C++?

最佳答案

正如评论中提到的,核心指南中的示例使用用户定义的文字来构造直观表示物理量的特定于应用程序的类型。为了在具体示例中说明它们,请考虑以下类型:

/* "Strong" speed type, unit is always [m/s]. */
struct Speed {
   long double value;
};

/* "Strong" length type, parameterized by a unit as multiples of [m]. */    
template <class Period = std::ratio<1>> struct Length {
   unsigned long long value;
};

跟踪 Length 对象的单位可能没有多大意义,但对于 Speed 实例则不然,但让我们在这里考虑最简单的示例。现在,让我们看看两个用户定义的文字:

#include <ratio>

auto operator ""_m(unsigned long long n)
{
   return Length<>{n};
}

auto operator ""_km(unsigned long long n)
{
   return Length<std::kilo>{n};
}

它们让您像这样实例化 Length 对象:

/* We use auto here, because the suffix is so crystal clear: */
const auto lengthInMeter = 23_m;
const auto lengthInKilometer = 23_km;

为了构造一个 Speed 实例,让我们定义一个合适的运算符来将 Length 除以 duration:

#include <chrono>

template <class LengthRatio, class Rep, class DurationRatio>
auto operator / (const Length<LengthRatio>& lhs,
      const std::chrono::duration<Rep, DurationRatio>& rhs)
{
   const auto lengthFactor = static_cast<double>(LengthRatio::num)/LengthRatio::den;
   const auto rhsInSeconds = std::chrono::duration_cast<std::chrono::seconds>(rhs);

   return Speed{lengthFactor*lhs.value/rhsInSeconds.count()};
}

现在,让我们再次看一下核心指南中的示例,

void change_speed(const Speed& s)
{
    /* Complicated stuff... */
}

但最重要的是,如何调用这样的函数:

using namespace std::chrono_literals;

int main(int, char **)
{
   change_speed(23_m/1s);
   change_speed(42_km/3600s);
   change_speed(42_km/1h);

   return 0;
}

正如评论中提到的@KillzoneKid,需要 C++11 才能工作。

关于c++ - C++ 中类型的单位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51943434/

相关文章:

c++ - 使用消息在 ROS 上发送 C 数组

c++ - 如何迭代以获取自定义 map ?

c++ - 是否有合法的方式从 gsl::not_null<T> 转移?

c++ - 使用模板来提高代码的抽象层次?

c++ - 如何处理来自核心准则检查器的有关gsl::at的静态分析警告?

c++ - range::view::transform 产生一个 InputIterator 阻止使用 std::prev

c++ - 在 C++ 中计算连续次数?

c++ - 未声明的标识符自定义类

c++ - 修改 not_null 以禁止与 nullptr 进行比较

c++ - 核心 cpp 指南中 f(T*, int) 接口(interface)与 f(span<T>) 接口(interface)的含义