简体   繁体   English

C++如何实现模板化转换二元运算符重载

[英]C++ how to implement templated converting binary operator overloads

I'm trying to do this:我正在尝试这样做:

template<class Float>
struct Number {
  Float v;
  Number(Float iv = 0) : v(iv) {}
};

template<class F>
Number<F> operator+(Number<F> const& a, Number<F> const& b) {   
  return {a.v + b.v};
}

int main() {
  Number<float> y = Number<float>(1) + 2.0f;
  std::cout << y.v << "\n";
}

But it doesn't work.但它不起作用。

main.cpp:15:38: error: invalid operands to binary expression ('Number<float>' and
      'float')
  Number<float> y = Number<float>(1) + 2.0f;
                    ~~~~~~~~~~~~~~~~ ^ ~~~~
main.cpp:10:11: note: candidate template ignored: could not match
      'Number<type-parameter-0-0>' against 'float'
Number<F> operator+(Number<F> const& a, Number<F> const& b) {   
          ^

And for some reason, this does work:出于某种原因,这确实有效:

struct Number {
  float v;
  Number(float iv = 0) : v(iv) {}
};

Number operator+(Number const& a, Number const& b) { 
  return {a.v + b.v};
}

int main() {
  Number x = Number(1) + 2.0f;
  std::cout << x.v << "\n";
}

But I want the template case to work.但我希望模板案例能够正常工作。 Basically I'm looking for any kind of workaround to enable me to implement binary operators for Number that will allow one of the args to be something convertible to Number.基本上,我正在寻找任何一种解决方法,以使我能够为 Number 实现二进制运算符,这将允许其中一个 args 可以转换为 Number。 Preferably c++14 compliant.最好符合 c++14。

Edit: based on Richard's link below, I came up with this which seems to handle the multiple conversions case but still unfortunately requires 3 overloads of each operator:编辑:基于下面理查德的链接,我想出了这个似乎可以处理多次转换的情况,但不幸的是仍然需要每个运算符的 3 个重载:

template<class T>
struct identity {
  using type = T;
};

template<class T>
using convertible = typename identity<T>::type;

template<class Float>
struct Param {
  Float v;
};

template<class Float>
struct Number {
  Float v;
  Number(Float iv = 0) : v(iv) {}
  Number(Param<Float> iv) : v(iv.v) {}
};

template<class F>
Number<F> operator+(Number<F> const& a, Number<F> const& b) {
  return {a.v + b.v};
}
template<class F>
Number<F> operator+(Number<F> const& a, convertible<Number<F>> const& b) {
  return {a.v + b.v};
}
template<class F>
Number<F> operator+(convertible<Number<F>> const& a, Number<F> const& b) {
  return {a.v + b.v};
}

int main() {
  std::cout << (Number<float>{1} + 2).v << "\n";
  std::cout << (Number<float>{1} + Param<float>{2}).v << "\n";
  std::cout << (Param<float>{1} + Number<float>{2}).v << "\n";
  std::cout << (Number<float>{1} + Number<float>{2}).v << "\n";
  std::cout << (1 + Number<float>{2}).v << "\n";
}

Implicit conversions won't be considered in template argument deduction . 模板参数推导中不会考虑隐式转换。

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution , which happens later.类型推导不考虑隐式转换(除了上面列出的类型调整):这是 重载决议的工作,稍后会发生。

So the deduction for template parameter F failed on the 2nd function parameter b in Number(1) + 2.0f , the implicit conversion from float to Number<float> won't be considered.因此Number(1) + 2.0f中第二个 function 参数b对模板参数F的推导失败,不考虑从floatNumber<float>的隐式转换。

You can add another two overloads as您可以添加另外两个重载为

template<class F, class V>
Number<F> operator+(Number<F> const& a, V const& b) {   
  return {a.v + Number{b}.v};
}

template<class F, class V>
Number<F> operator+(V const& a, Number<F> const& b) {   
  return {Number{a}.v + b.v};
}

LIVE居住

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM