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.