操作符重载和不同的模板参数
Operator overloading and different template parameter
在模板化类中重载操作符+有问题。假设我有
template<typename T>
struct point{
//Ctors:
point(){};
point(T _x, T _y):x(_x),y(_y){};
point(const point<T>& p):x(p.x),y(p.y){};
template<typename T2>
point(const point<T2>& p):x(static_cast<T>(p.x)),y(static_cast<T>(p.y)){};
//Coordinates:
T x;
T y;
//Operator overloads:
friend point<T> operator+(point<T> left,point<T> right ){
return point<T>(left.x+right.x, left.y+right.y);
}
template<class T2>
friend point<T> operator+(point<T2> left,point<T> right){
return point<T>(left)+right;
}
template<class T3>
friend point<T> operator+(point<T> left,point<T3> right){
return point<T>(right)+left;
}
};
在调用。
时会产生歧义错误。point<float> p1(1.2,1.4);
point<int> p2(1,2);
point<float> p3 =p1+p2;
这很有意义,但是你能告诉我如何解决这个问题吗?
我需要3个操作符,否则转换可能会走向错误的方向。例如,忽略最后一个操作符重载将导致p3.x=2
和p3.y=4
。
非常感谢!
在某种程度上,这是个人偏好和主观意见的问题,但我认为我会尝试模仿普通的c++规则来处理算术表达式的结果类型,例如
template <class T1, class T2 >
friend
auto operator+( Point<T1> const left, Point<T2> const right )
-> Point< decltype( left.x + right.x ) >
{
return {left.x + right.x, left.y + right.y};
}
同时满足g++ 4.8.2和visualc++ 12.0的要求比我想象的要复杂得多,但下面的具体代码可以在这两个编译器中清晰地编译:
#include <type_traits>
#include <utility>
template< class Number >
struct Point
{
Number x;
Number y;
};
template< class T1, class T2 >
auto operator+( Point<T1> const left, Point<T2> const right )
-> Point< typename std::remove_const<decltype( left.x + right.x )>::type >
{
using Result_number =
typename std::remove_const<decltype( left.x + right.x )>::type;
using Result_point = Point< Result_number >;
return Result_point{ left.x + right.x, left.y + right.y };
}
auto main()
-> int
{
Point<float> const p1{ 1.2, 1.4 };
Point<int> const p2{ 1, 2 };
Point<float> const p3 = p1 + p2;
}
为了方便Point
的可能的窄化转换,可以添加一个显式的转换操作符成员函数,如下所示:
template< class Number >
struct Point
{
Number x;
Number y;
template< class Other_number >
explicit
operator Point<Other_number>() const
{
return Point<Other_number>{
static_cast<Other_number>( x ),
static_cast<Other_number>( y )
};
}
};
调用使用任何合适的强制转换,例如明显的构造函数表示法(上面的定义只是调用转换操作符的强制转换):
Point<int> const p4 = Point<int>( p1 + p2 );
如果您想在result参数的类型中使用result,则创建计算它的方法:
template<class T, class T2, class T3>
void AddPoints(const point<T>& a, const point<T2>& b, point<T3>& result)
{
result = point<T3>(a) + point<T3>(b);
}
int main()
{
point<float> p1(1.2,1.4);
point<int> p2(1,2);
point<double> result;
AddPoints(p1, p2, result);
}
相关文章:
- 使用模板参数重载C++方法:如何使其适用于模板的子类?
- 如何使用类的参数重载运算符+?
- 为什么我不能用两个参数重载 C++ 运算符 []?
- 模板化类参数重载
- 模板参数重载,最后一个参数为非类型名
- MSVC编译器错误将模板与枚举参数重载时
- std::map:使用键类以外的参数重载运算符<
- C++用参数重载友元类函数参数
- 如何在参数重载解析中禁用隐式转换为指向 void 的指针
- 使用可选参数重载 new 和 delete 运算符
- 如何通过参数函子参数重载函数切换
- 同时使用参数重载和返回类型重载
- 特征3,并根据模板参数重载新算子,以确保正确对齐
- C++使用默认参数重载
- 单例方案,使用不同的参数重载 getInstance
- 具有'const'参数重载的可变参数模板
- 是fill_n,并填充相同的函数,但具有不同的参数重载
- 用不同的参数重载运算符两次
- 模板非类型参数重载
- 无法推断模板参数/'n'重载都无法覆盖所有参数类型