3D 向量的高效除法运算符

Efficient division operator for 3D vectors

我有一个简单的 class 3D 矢量模板:

template <typename T>
struct Vec3
{
    T x, y, z;  // vector components
    ...
}

其中模板参数 T 可以是 intfloatdouble(目前无论如何)。重载除法运算符时我有两个要求:

我想到了这个简短的实现:

template <typename = std::enable_if_t<std::is_floating_point_v<T>>>
Vec3 operator/(T a) const
{
    assert(a != 0);
    T inva = static_cast<T>(1.0)/a;
    return Vec3{inva*x, inva*y, inva*z};
}

关于这段代码的几个问题:

编辑:gcc 不介意,但 clang 不会编译上面的代码。这是因为我对 SFINAE 的使用不正确。正确的实施方式是

template <typename U = T,
          typename = std::enable_if_t<std::is_floating_point_v<U>>>
Vec3 operator/(T a) const
{
    ...
}

可以在此处找到更多详细信息:std::enable_if to conditionally compile a member function

  • Is there another non-SFINAE way to restrict this member function to floating point types? (I am using C++17)
  • class 的完全或部分专业化(对于部分专业化,需要进行更改以使 class SFINAE 友好)。
  • 重载为自由函数(因为 std::is_floating_point_v 仅适用于少数类型(floatdoublelong double(+ cv_variant)))

    Vec3<float> operator / (const Vec3<float>& vec, float value) {/*..*/}
    Vec3<double> operator / (const Vec3<float>& vec, float value) {/*..*/}
    Vec3<long double> operator / (const Vec3<float>& vec, float value) {/*..*/}
    

SFINAE 似乎是更好的选择。

C++20 将引入 requires 以彻底丢弃这些方法:

Vec3 operator/(T a) const requires(std::is_floating_point_v<T>) {/*..*/}
  • Are modern compilers smart enough to compute the division first and then perform three multiplications? Is it a waste of time and expressiveness to do that myself?

对于浮点数,结果可能不同,因此编译器不会这样做(除非它可以确保它会产生相同的结果)。

  • Is it worth using a variable template for the constant 1.0? Will the compiler be smart enough to do the static_cast at compile time?

我相信编译器会将代码 static_cast<float>(1.0) 替换为 1.f