当我们有 contexpr 值时 <ratio> 有什么用?

ein*_*ica 9 c++ c++11 c++20

<ratio>头允许您使用模板元编程来处理和操作有理值。

然而,它是在 C++11 中引入的,当时我们已经有了constexpr. 为什么有一个完全构造的有理数库类型还不够好,即基本上:

template<typename I>
struct rational { 
    I numerator;
    I denominator;
};
Run Code Online (Sandbox Code Playgroud)

并用它代替?

使用std::ratioC++11 constexpr 功能是否有一些不太适合的具体好处?如果是这样,它在 C++20 中是否仍然相关(随着 constexpr 的扩展“范围”)?

Hol*_*Cat 9

使用 std::ratio 是否有一些 C++11 constexpr 功能不太适合的具体好处?

您可以ratio作为模板类型参数传递,这就是作用std::chrono::duration。要使用基于值的比率来实现此目的,您需要 C++20 或更高版本。

在 C++20 及更新版本中,我没有看到当前设计的任何好处。

  • @KonradRudolph我不认为OP提出“双重”?我认为他们建议“template &lt;typename T&gt; structratio {T num, den;};”。 (2认同)
  • 当前设计的好处之一是:对于元编程来说,类型比值更容易处理。例如:如果ratio是类型参数,则`std::chrono::duration`适用于Boost.Mp11,但如果它是值参数,则不适用于Boost.Mp11。 (2认同)

Jak*_*ark 7

这里有几个答案和评论,但我认为它们都没有真正阐明 的要点std::ratio。让我们从 的定义开始std::ratio。它大致相当于:

template<int Num, int Den>
struct ratio {
    static constexpr int num = Num;
    static constexpr int den = Den;
};
Run Code Online (Sandbox Code Playgroud)

您可能会使用std::ratio类似以下内容的替代方案:

template<typename I>
struct ratio {
    I num;
    I den;
};
Run Code Online (Sandbox Code Playgroud)

有一堆constexpr函数来执行该类型的算术。

请注意,这两个定义之间存在微妙但非常重要的区别。在第二个定义中,比率(numden)的实际值存储在类型的实例中,而在第一个定义中,值实际上存储在类型本身中。

如果您有一个像 的库std::chrono,您需要一个类型,可以将时间存储为毫秒数(例如std::chrono::milliseconds)。如果稍后想要将此数字转换为秒,则不需要将转换比率编码到 的实例中std::chrono::milliseconds,而是编码到类型本身中。std::chrono这就是为什么使用第一种形式而不是第二种形式(或简单的浮点值)的原因。

要将数字存储到类型而不是实例中,您需要一个非类型模板参数。在 C++20 之前,您只能对非类型模板参数使用整数值。尽管如此,为了将合理的转换因子存储在标准库中,指定了std::ratio类模板。

在 C++20 中,潮流发生了一些变化,因为您现在可以使用浮点数作为非类型模板参数。例如std::chrono::duration可以重写为:

template<..., double conversion_factor, ...>
duration {
    ...
};
Run Code Online (Sandbox Code Playgroud)

然而,这个 C++20 功能与您在问题中提到的“constexpr 的扩展范围”无关。编译时间计算与在类型本身中存储数值不同,尽管您需要第一个来执行第二个。

类模板的使用std::ratio(专门)用于将值存储到类型中。