如何在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,您出于不明原因希望避免使用它。如果您只使用内置类型(double
、float
、int
等),您可以轻松实现自己的 common_type
版本。但是,如果您想进行复杂的元模板编程,强烈建议继续使用 C++11——它已经有 4 年历史了,而且大部分是向后兼容的。
如何才能使(具有不同模板类型的对象)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,您出于不明原因希望避免使用它。如果您只使用内置类型(double
、float
、int
等),您可以轻松实现自己的 common_type
版本。但是,如果您想进行复杂的元模板编程,强烈建议继续使用 C++11——它已经有 4 年历史了,而且大部分是向后兼容的。