使用不同的模板类型从 class 转换为相同的 class
Conversion from class to identical class with different template types
我有简单的class“vec2”。我希望 class 能够在 class 模板中存储双精度和双精度引用,甚至是 int 和 int 引用。这是所需的行为-
vec2<double> base(5, 5); //normal vec2
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
vec2<double> third;
base.x++; //base.x equals 6, this also changes reference.x to 6;
third = reference; //conversion between vec2<double> and vec2<double&>
我还想修改 vec2 的引用实例是不可能的,除非通过更改它引用的变量 - 所以下面的代码会产生编译器错误
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
reference.x = 5; //undesired behaviour
有没有办法让成员 x 和 y public 在处理非引用 class 类型时,但在 class 类型是引用时是私有的?这将需要特定于何时将 return x 和 y 的值作为参考的方法。在引用版本中,它还需要没有可能影响引用的重载运算符方法。我对模板特化略有了解,但还不足以真正实现它。
无论如何,本文的要点是找出如何获取 vec2<double>
类型的 class,并将其转换为 vec2<double&>
类型的 class .
或者,相反地,将 vec2<double&>
类型的 class 转换为 vec2<double>
.
类型的 class
这是我的简单 vec2 class-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
void normalize(){ //this function should inaccesable to any "reference version" of vec2
*this /= magnitude();
}
void rotate(double radians, vec2 center){ //this should also be inaccesable to reference versions
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y); //this should be available to both
}
T x;
T y;
vec2 operator+(const vec2 &v) const{ //available to both
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{ //available to both
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{ //available to both
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){ //inaccesable to reference versions of the class
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){ //inaccesable to reference versions
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){ //inaccesable to reference versions
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){ //inaccesable to reference versions
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){ //inaccesable to reference versions
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{ //this should be available to both
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{ //this should be available to both
return (v.x != x || v.y != y);
}
};
非常感谢任何帮助!我没有太多使用模板,事实上,我昨天才开始!提前感谢您的宝贵时间!
简化版。通过将这些字段设为私有,它们就不能被修改。我没有尝试实现所有 operator= 方法,但您的代码应该可以工作。
我不太确定你的困惑在哪里。扫描没有发现任何问题,除了我将这些字段设为私有以便没有人可以触摸它们,并改为添加访问器方法。
#include <iostream>
using namespace std;
template <class T>
class MyClass {
private:
T x;
T y;
public:
MyClass(T _x, T _y) : x(_x), y(_y) {}
T getX() const { return x; }
T getY() const { return y; }
};
int main(int, char **) {
double x {1.0};
double y {2.5};
MyClass<double> withDouble(x, y);
MyClass<double &> withRef{x, y};
cout << "withDouble: " << withDouble.getX() << ", " << withDouble.getY() << endl;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
x = 3.9;
y = 5.4;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
}
我做了更多的研究,并设法在模板专业化方面学到了很多东西。这是功能性的 vec2 class,它实现了我想要的一切,加上一个“perpindiculate”函数和一个“swap”函数-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
operator vec2<T&>(){
return vec2<T&>(x, y);
}
void swap(){
std::swap(x, y);
}
void perpindiculate(){
std::swap(x, y);
y = -y;
}
void normalize(){
*this /= magnitude();
}
void rotate(double radians, vec2 center){
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T x;
T y;
};
template<class T>
class vec2<T&>{
public:
vec2(T& X, T& Y) : x{X}, y{Y} {}
operator vec2<T>(){
return vec2<T>(x, y);
}
vec2<T> swap() const{
return vec2<T>(y, x);
}
vec2<T> perpindiculate() const{
return vec2<T>(-y, x);
}
vec2<T> normalize() const{
return *this / magnitude();
}
vec2<T> rotate(double radians, vec2 center) const{
return vec2<T>(x*cos(radians) - y*sin(radians), y*cos(radians) + x*sin(radians));
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T& v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T& v) const{
return vec2(x/v, y/v);
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T getx(){
return x;
}
T gety(){
return y;
}
private:
T& x;
T& y;
};
这是一个工作的例子-
double x = 5; //create future reference variables
double y = 3;
vec2<double&> vecref(x, y); //create vec2 referring to x and y
x = 7; //change x and y values, also changing vecref's values as well
y = 8;
vec2<double> vecOffRef = vecref; //conversion from a reference vec to a normal one
vec2<double&> vecOffRefref = vecOffRef; //conversion from a normal vec to a reference one
vecOffRef.normalize(); //normalize vec, also normalizing vecOffRefref
/* x equals 7, y = 8
vecRef equals (7, 8)
vecOffRef equals (0.6585, .7525)
vecOffRefRef equals (0.6585, .7525) */
我有简单的class“vec2”。我希望 class 能够在 class 模板中存储双精度和双精度引用,甚至是 int 和 int 引用。这是所需的行为-
vec2<double> base(5, 5); //normal vec2
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
vec2<double> third;
base.x++; //base.x equals 6, this also changes reference.x to 6;
third = reference; //conversion between vec2<double> and vec2<double&>
我还想修改 vec2 的引用实例是不可能的,除非通过更改它引用的变量 - 所以下面的代码会产生编译器错误
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
reference.x = 5; //undesired behaviour
有没有办法让成员 x 和 y public 在处理非引用 class 类型时,但在 class 类型是引用时是私有的?这将需要特定于何时将 return x 和 y 的值作为参考的方法。在引用版本中,它还需要没有可能影响引用的重载运算符方法。我对模板特化略有了解,但还不足以真正实现它。
无论如何,本文的要点是找出如何获取 vec2<double>
类型的 class,并将其转换为 vec2<double&>
类型的 class .
或者,相反地,将 vec2<double&>
类型的 class 转换为 vec2<double>
.
这是我的简单 vec2 class-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
void normalize(){ //this function should inaccesable to any "reference version" of vec2
*this /= magnitude();
}
void rotate(double radians, vec2 center){ //this should also be inaccesable to reference versions
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y); //this should be available to both
}
T x;
T y;
vec2 operator+(const vec2 &v) const{ //available to both
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{ //available to both
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{ //available to both
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){ //inaccesable to reference versions of the class
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){ //inaccesable to reference versions
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){ //inaccesable to reference versions
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){ //inaccesable to reference versions
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){ //inaccesable to reference versions
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{ //this should be available to both
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{ //this should be available to both
return (v.x != x || v.y != y);
}
};
非常感谢任何帮助!我没有太多使用模板,事实上,我昨天才开始!提前感谢您的宝贵时间!
简化版。通过将这些字段设为私有,它们就不能被修改。我没有尝试实现所有 operator= 方法,但您的代码应该可以工作。
我不太确定你的困惑在哪里。扫描没有发现任何问题,除了我将这些字段设为私有以便没有人可以触摸它们,并改为添加访问器方法。
#include <iostream>
using namespace std;
template <class T>
class MyClass {
private:
T x;
T y;
public:
MyClass(T _x, T _y) : x(_x), y(_y) {}
T getX() const { return x; }
T getY() const { return y; }
};
int main(int, char **) {
double x {1.0};
double y {2.5};
MyClass<double> withDouble(x, y);
MyClass<double &> withRef{x, y};
cout << "withDouble: " << withDouble.getX() << ", " << withDouble.getY() << endl;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
x = 3.9;
y = 5.4;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
}
我做了更多的研究,并设法在模板专业化方面学到了很多东西。这是功能性的 vec2 class,它实现了我想要的一切,加上一个“perpindiculate”函数和一个“swap”函数-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
operator vec2<T&>(){
return vec2<T&>(x, y);
}
void swap(){
std::swap(x, y);
}
void perpindiculate(){
std::swap(x, y);
y = -y;
}
void normalize(){
*this /= magnitude();
}
void rotate(double radians, vec2 center){
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T x;
T y;
};
template<class T>
class vec2<T&>{
public:
vec2(T& X, T& Y) : x{X}, y{Y} {}
operator vec2<T>(){
return vec2<T>(x, y);
}
vec2<T> swap() const{
return vec2<T>(y, x);
}
vec2<T> perpindiculate() const{
return vec2<T>(-y, x);
}
vec2<T> normalize() const{
return *this / magnitude();
}
vec2<T> rotate(double radians, vec2 center) const{
return vec2<T>(x*cos(radians) - y*sin(radians), y*cos(radians) + x*sin(radians));
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T& v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T& v) const{
return vec2(x/v, y/v);
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T getx(){
return x;
}
T gety(){
return y;
}
private:
T& x;
T& y;
};
这是一个工作的例子-
double x = 5; //create future reference variables
double y = 3;
vec2<double&> vecref(x, y); //create vec2 referring to x and y
x = 7; //change x and y values, also changing vecref's values as well
y = 8;
vec2<double> vecOffRef = vecref; //conversion from a reference vec to a normal one
vec2<double&> vecOffRefref = vecOffRef; //conversion from a normal vec to a reference one
vecOffRef.normalize(); //normalize vec, also normalizing vecOffRefref
/* x equals 7, y = 8
vecRef equals (7, 8)
vecOffRef equals (0.6585, .7525)
vecOffRefRef equals (0.6585, .7525) */