避免模​​板化运算符重载的隐式参数转换

时间:2018-02-14 19:54:04

标签: c++ templates operator-overloading implicit-conversion

我的问题是,如何防止显示的行为,但正如Cheersandhth.-Alf指出的那样,我没有包含导致此问题的构造函数。 现在包含了构造函数,很明显,将float(以及其他任何东西)转发到std :: array ctor导致了这个问题。

我仍然希望能够使用这种初始化Vec2 a = {1.f, 2.f},但转发ctor非常危险,所以我会避免这种情况。

我有一个从std :: array派生的Vec类,它应该通过运算符重载实现通常的组件式算术运算。运算符应该同时用于相同类型和大小的其他Vecs(在这种情况下对相应的向量组件进行操作),以及整数和浮点类型。

e.g。

{1.f, 2.f, 3.f} * 2.f = {2.f, 4.f, 6.f}
{1.f, 0.f} + {0.f, 1.f} = {1.f, 1.f}

以下是我所做的事情(仅针对运营商*展示)https://godbolt.org/g/PtCkzR

template<class T, size_t N>
class Vec : public std::array<T, N>
{
public:
  template<typename... S>
  Vec(S&&... params) : std::array<T, N>{std::forward<S>(params)...} { };

  friend Vec<T, N>& operator*=(Vec<T, N>& a, const Vec<T, N>& b)
  {
    std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::multiplies<>());
    return a;
  }

  template<class S>
  friend Vec<T, N>& operator*=(Vec<T, N>& a, const S& b)
  {
    std::transform(a.begin(), a.end(), a.begin(), [&] (T x) { return x*b; });
    return a;
  }

  template<class S>
  friend Vec<T, N> operator*(Vec<T, N> a, const S& b)
  {
    return a *= b;
  }
};
using Vec2 = Vec<float, 2>;

现在,当我想将一个向量与浮点相乘时,会发生这种情况:

Vec2 a{1.f, 1.f};
auto b = a * 0.5f; // b = {.5f, .5f} <- as expected
auto c = 0.5f * a; // c = {.5f, 0.f} <- what happened here?

这是因为第三行中的0.5f被隐式转换为Vec2 {0.5f, 0.f},然后传递给operator*(Vec2, const Vec2&)重载。

1 个答案:

答案 0 :(得分:0)

添加另一个operator*重载函数,其中LHS可以是数字。

template<class S>
   friend Vec<T, N> operator*(S b, Vec<T, N> a)
   {
      return a *= b;
   }