【问题标题】:How to create a class specialization that does different things for floats and ints?如何创建一个为浮点数和整数做不同事情的类专业化?
【发布时间】:2021-06-04 09:26:34
【问题描述】:

我想创建一个名为 Vec2 的结构,它看起来像这样:

template<typename T>
struct Vec2 {
  T x, y;

  // Other things are also there like Constructors, Destructors, operator overloads, etc.
};

我希望能够为 % 运算符创建运算符重载。重载看起来像这样

Vec2<T> operator%(const Vec2<T> &other) {
  return Vec2<T>(this-> x % other.x, this.y % other.y);
}

现在的问题是,如果有人使用 float 模板参数实例化此结构,则此运算符重载会中断,因为您不能使用 C++ 中的默认 % 运算符对浮点数进行模运算。所以在那种情况下,我想改用这个函数。

Vec2<T> operator%(const Floating &other) {
  return Vec2<T>(fmod(this->x, other.x), fmod(this->y, other.y));
}

那么我该怎么做,如果有人用 float 作为模板参数来实例化这个结构,那么他们应该可以访问第二个运算符重载,否则第一个。

我已经设法创建了一个模板,可以帮助我过滤掉所有像这样的浮动模板参数

template<typename T,
         typename  = std::enable_if_t<std::is_floating_point_v<Integral>>>
struct Vec2 {
  T x, y;

  // Other things are also there like Constructors, Destructors, operator overloads, etc.
  Vec2<T> operator%(const Vec2<T> &other) {
    return Vec2<T>(fmod(this->x, other.x), fmod(this->y, other.y));
  }
};

这使得没有人可以用 Integral 值实例化这个类。但我不希望这种情况发生。我希望他们也能够使用 Integral 值来实例化这个类,只是使用不同的成员函数。怎样才能做到这一点?我试过做一些部分专业化,但没有成功。

注意:在我的实际代码中,我的结构略有不同,基类包含所有常见代码,但为简单起见,我没有在此处包含它。

我使用的是 GCC 11.1.0。 C++ 标准并不重要,因为我什至可以使用 C++20。

【问题讨论】:

    标签: c++ templates operator-overloading typetraits


    【解决方案1】:

    在这种情况下,一个简单的if constexpr 就足够了:

    Vec2<T> operator%(const Vec2<T> &other) 
    {
        if constexpr (std::is_floating_point_v<T>)
        {
            return Vec2<T>(fmod(this->x, other.x), fmod(this->y, other.y));
        }
        else 
        {
            return Vec2<T>(this-> x % other.x, this->y % other.y);
        }
    }
    

    这里我使用std::is_floating_point_v 在编译时确定T 是否为任何浮点类型。两个分支中只有一个会出现在各自的模板实例化中。

    我认为这比专门针对浮点/非浮点的整个模板要简单得多,而且在我看来比 SFINAE 更具可读性。

    【讨论】:

    • 非常感谢您的回答。我曾考虑过这种方法,但想走 SFINAE 路线。现在我想起来了,这实际上更具可读性,因此我将其标记为正确答案。非常感谢您的帮助:)
    猜你喜欢
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多