模板化数学函数应该采用值还是 const 引用?

Should templated math functions take values or const references?

假设我想实现一些简单的数学函数;例如,假设它是 (C++17's) std::clamp 的重新实现:此函数接受一个数字、一个下限和一个上限,如果该数字超出它们定义的范围,则将其设置为这些界限之一.如果是具体的数字类型,比如int,我会写:

constexpr int clamp(int x, int lower_bound, int upper_bound)
{
    return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

但如果它是一个模板,我看到 sample implementation 可能是标准将要使用的 const& 而不是值。因此,使引用更简单,例如:

template <typename T>
constexpr T clip(const T& x, const T& lower_bound, const T& upper_bound)
{
    return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

我的问题是:

备注:

Is there any benefit to taking a const reference, for T's which are simple numeric types?

不,我不这么认为,但也没有处罚。

Ditto, for types which are some abstract thing wrapping a single number as a data member (e.g. a std::chrono duration)?

同上。

Why is it (and is it at all) a better idea to take a const& then a value in the general case?

标准库算法不仅适用于基本类型,也适用于用户定义的类型,复制这些类型可能并不便宜。对于这些类型,使用 const& 可以避免复制的惩罚,同时不会损害基本类型的用法。

  • Is there any benefit to taking a const reference, for T's which are simple numeric types?

没有

  • Ditto, for types which are some abstract thing wrapping a single number as a data member (e.g. a std::chrono duration)?

没有

  • Why is it (and is it at all) a better idea to take a const& than a value in the general case of any relatively-simple, (constexpr?), side-effect-free math-ish function?

想象一个使用动态分配的 bigint 类型;复制这样的类型很昂贵。

  • Wouldn't a compiler optimize the copying away?

只有它能证明复制值没有副作用,这很难做到,除非涉及的所有代码对编译器都是可见的。 (所以,如果你的 bigint 使用 GMP,那你就不走运了。)