简体   繁体   中英

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

How can I make it so that (with objects of different template types) A*B and B*A give the same result, where the type of the result is determined according to the usual C++ type promotion rules ?

For example:

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

At the moment, I can only multiply objects of the same template type. For example, something like this:

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

EDIT: Or, as in the answers, I can multiply objects of different template types, but always returning the same type as lhs . Is there any way to instead return an object whose type is determined by the standard type promotion rules?

EDIT 2: I would like to avoid C++11 features if possible .

You have to templatize eg the rhs parameters:

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

You need a templated overload for the operator*()

template<typename T>
class number {
    public:
    // ...
    template<typename U>
    number& operator*=(const number<U>& rhs) {
        // ...
    }
    // ...
 };

And the same for the binary operator

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

You can use std::common_type<> to obtain the type required for the return. For example

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

I left out the implementations of the templated constructor and operator*= .


Unfortunately, std::common_type is C++11, which you want to avoid for obscure reasons. If you only work with built-in types ( double , float , int , etc), you can easily implement your own version of common_type . However, if you want to do sophisticated meta-template programming, it is strongly recommended to move on to C++11 – it's already 4 years old and mostly backwards compatible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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