如何在C++中将不同模板类型的对象相乘

How to multiply objects of different template type in C++

如何才能使(具有不同模板类型的对象)A*B 和 B*A 给出相同的结果,其中结果的类型是根据通常的 C++ 确定的类型提升规则?

例如:

int main()
{
    number<float> A(2.0f);    
    number<double> B(3.0);
    A*B; // I want 6.0 (double)
    B*A; // I want 6.0 (double)

    return 0;
}

目前,我只能将相同模板类型的对象相乘。例如,像这样:

template<typename T>
class number
{
    public:

        number(T v) : _value(v) {}

        T get_value() const { return _value; }

        number& operator*=(const number& rhs)
        {
            _value *= rhs.get_value(); 
            return *this;
        } 

    private:

        T _value;
};

template<typename T>
inline number<T> operator*(number<T> lhs, const number<T>& rhs)
{
  lhs *= rhs;
  return lhs;
}

编辑:或者,如答案所示,我可以乘以不同模板类型的对象,但总是returning 与 lhs 相同的类型。有什么方法可以代替 return 类型由标准类型提升规则确定的对象吗?

编辑 2:我想尽可能避免使用 C++11 功能

您需要 operator*()

的模板化重载
template<typename T>
class number {
    public:
    // ...
    template<typename U>
    number& operator*=(const number<U>& rhs) {
        // ...
    }
    // ...
 };

二元运算符也一样

template<typename T,typename U>
inline number<T> operator*(number<T> lhs, const number<U>& rhs) {
  lhs *= rhs;
  return lhs;
}

你必须模板化,例如rhs参数:

template<typename T>
class number
{
public:

    number(T v) : _value(v) {}

    T get_value() const { return _value; }
    template<class E>
    number& operator*=(const number<E>& rhs)
    {
        _value *= rhs.get_value(); 
        return *this;
    } 

private:

    T _value;
};

template<class T, class E, class RET = decltype(T()*E())>
number<RET> operator*(number<T>& lhs, const number<E>& rhs)
{
    return lhs.get_value()*rhs.get_value();
}

您可以使用std::common_type<>获取return所需的类型。例如

template<typename X>
struct number
{
  // ...

  template<typename Y>
  number(number<Y> const&other);              // needed in line 1 below

  template<typename Y>
  number&operator=(number<Y> const&other);    // you may also want this

  template<typename Y>
  number&operator*=(number<Y> const&other);   // needed in line 2 below

  template<typename Y>
  number<typename std::common_type<X,Y>::type> operator*(number<Y> const&y) const
  {
    number<typename std::common_type<X,Y>::type> result=x;   // 1
    return result*=y;                                        // 2
  }
};

我省略了模板构造函数和 operator*= 的实现。


不幸的是,std::common_type 是 C++11,您出于不明原因希望避免使用它。如果您只使用内置类型(doublefloatint 等),您可以轻松实现自己的 common_type 版本。但是,如果您想进行复杂的元模板编程,强烈建议继续使用 C++11——它已经有 4 年历史了,而且大部分是向后兼容的。