c++ - 3D vector 的高效除法运算符

标签 c++ operator-overloading division sfinae micro-optimization

我有一个简单的 3D vector 类模板:

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};
}

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

  • 是否有另一种非 SFINAE 方法将此成员函数限制为 float 点类型? (我正在使用 C++17)
  • 现代编译器是否足够聪明,可以先计算除法,然后 然后执行三次乘法?是不是浪费时间 和表现力自己做这件事?
  • 是否值得为常量 1.0 使用变量模板?编译器是否足够聪明,可以在编译时执行 static_cast ? C++ static_cast runtime overhead

    template<typename T>
    constexpr T one = T(1.0);
    

编辑: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)
  • 类的完全或部分特化(对于部分特化,需要进行更改以使类 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?

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

  • 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 .

关于c++ - 3D vector 的高效除法运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57671777/

相关文章:

c++ - 如何使用 clang 和 distcc 在不同架构的从机上编译(例如 Mac/Linux)

c++ - 光线追踪程序中的全向光给出了错误的渲染 C++

c++ - 向 QTabWidget 添加选项卡后 Qt App 崩溃

c++ - 引用或复制结构的结构(分配了 memset)是有效的事情吗?

c++ - Vector size() 返回看似随机的大整数

c++ - 为什么 "no match for ' operator <'"当我声明的时候?

c++ - 如何在数组中的对象上调用 << 运算符?

python - 如何在本地重新定义 __truediv__ 以返回 Fraction

C 'float' 生成随机答案

algorithm - 需要知道这是否是一种独特的划分方式?