Change values of struct with overloaded operator [] - c++

I'm trying to make a custom vector data structure. It will always contain 4 float values. I want to make it accessible via its attributes names, but also through operator [ ], so it could be also accessed with index like e.g. array. It should be editable through operator [ ], like vector or array.
I've done so far this:
struct vec4
{
float* x;
float* y;
float* z;
float* w;
vec4() : data(4, 0.0f) { Init(); }
vec4(float x, float y, float z, float w)
{
data = std::vector<float>{ x, y, z, w };
Init();
}
float* operator[](int i) const
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
default: __debugbreak();
}
}
private:
std::vector<float> data;
void Init()
{
std::vector<float>::iterator start = data.begin();
this->x = &(*++start);
this->y = &(*++start);
this->z = &(*++start);
this->w = &(*start);
}
};
Is there any more elegant way how to solve this problem?

Having individual members and then using a switch statement is pretty much the way to do this. You don't need the vector though and can write the class like
struct vec4
{
float x = 0;
float y = 0;
float z = 0;
float w = 0;
vec4() = default;
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
const float& operator[](int i) const
{
switch (i)
{
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
default: __debugbreak();
}
}
float& operator[](int i)
{
// this is safe because we are in a non-const function, so this cant point to a const object
return const_cast<float&>(static_cast<const vec4&>(*this)[i]);
}
};

How about
struct vec4
{
vec4() : vec4(0, 0, 0, 0) {}
vec4(float x, float y, float z, float w) : data{ x, y, z, w } {}
float operator[](int i) const { return data[i]; }
float& operator[](int i) { return data[i]; }
float at(int i) const { return data.at(i); }
float& at(int i) { return data.at(i); }
float x() const { return data[0]; }
float y() const { return data[1]; }
float z() const { return data[2]; }
float w() const { return data[3]; }
float& x() { return data[0]; }
float& y() { return data[1]; }
float& z() { return data[2]; }
float& w() { return data[3]; }
private:
std::array<float, 4> data;
};

Related

How do I simulate C#'s {get; set;} in C++?

I am experimenting with lambda functions and managed to recreate a "get" functionality in C++. I can get the return value of a function without using parentheses. This is an example class, where I implement this:
using namespace std;
struct Vector2 {
float x;
float y;
float length = [&]()-> float {return sqrt(x * x + y * y); }();
float angle = [&]()-> float {return atan2(y, x); }();
Vector2() : x(0), y(0) {}
Vector2(float a, float b) : x(a), y(b) {}
~Vector2() {}
Vector2(Vector2& other) : x(other.x), y(other.y) {}
Vector2(Vector2&& other) = delete;
void operator =(Vector2&& other) noexcept{
x = other.x;
y = other.y;
}
};
int main()
{
Vector2 vec = Vector2(10, 17);
printf("%f\n%f\n%f\n%f\n", vec.x, vec.y, vec.length, vec.angle);
}
However, I am currently trying to also recreate the "set" functionality that C# has. But I'm failing. I tried to add this:
void angle = [&](float a)->void {
float l = length;
x = cos(a) * l;
y = sin(a) * l;
};
But am getting "Incomplete type is not allowed" error. I'm not sure if that's how it should look, even if I wasn't getting the error. Is it even possible to recreate the "set" functionality C# has in C++?
I know that I can just use a method SetAngle(float a){...}, but that's not really the point.
TL;DR: Don't
What you have isn't a getter, it's just a normal data member that's calculated once when the object is initialized.
In general, C++ doesn't support C#-style properties. The usual C++-style solution is to just use a pair of member functions (and maybe a data member, if you need to save the value separately), i.e.
struct Vector2 {
// ...
float length() const { return sqrt(x * x + y * y); }
void length(float l) {
float angle = angle();
float new_x = l * cos(angle);
float new_y = l * sin(angle);
x = new_x;
y = new_y;
}
// ...
};
You can get something close to a C#-style property, but you'll always run into edge-cases where they don't work perfectly. For example, here's something that will work in many cases:
template <typename T>
class Property
{
private:
std::function<T()> getter_;
std::function<void(const T&)> setter_;
public:
Property(std::function<T()> getter, std::function<void(const T&)> setter)
: getter_{getter},
setter_{setter}
{}
operator T()
{
return getter_();
}
const T& operator=(const T& val)
{
setter_(val);
return val;
}
};
struct Vector2
{
float x;
float y;
Property<float> length{
[this]() { return sqrt(x * x + y * y); },
[this](float l) {
float new_x = l * cos(angle);
float new_y = l * sin(angle);
x = new_x;
y = new_y;
}
}
Property<float> angle{
[this]() { return atan2(y, x); },
[this](float a) {
float l = length;
x = cos(a) * l;
y = sin(a) * l;
}
}
// ...
};
int main() {
Vector2 v;
v.x = 1;
v.y = 1;
v.angle = std::numbers::pi / 2;
std::cout << "(" << v.x << ", " << v.y << ")\n";
}
But this still falls apart in the edge cases, especially when you mix it with templates and/or auto type-deduction. For instance:
Vector2 v;
v.x = 1;
v.y = 1;
auto old_angle = v.angle;
v.angle = std::numbers::pi / 2;
// oops, this prints pi/2, not pi/4 like you probably expected
// because old_angle isn't a float, it's a Property<float> that
// references v
std::cout << old_angle << '\n';
Note also that there's a bug here. Consider this:
int main() {
Vector2 v1;
v1.x = 1;
v1.y = 1;
Vector2 v2 = v1;
v2.angle = std::numbers::pi / 2;
// Oops, assigning to v2.angle modified v1
std::cout << "(" << v1.x << ", " << v1.y << ")\n";
}
You could work around these issues by making Property non-copyable, but then you force any class that uses it to implement a custom copy-constructor. Also, while that would make the auto case "safe", it does so by turning it into a compile error. Still not ideal.
I agree with Miles. This is not the greatest idea, because it's unnatural for C++ developers, and you should write code that is first and foremost easy to read.
However, as an engineering challenge, here's a possible implementation:
#include <math.h>
#include <iostream>
template <typename T>
class Member
{
public:
operator T() const { return _value; }
void operator =(const T& value) const { _value = value; } void operator =(T&& value) { _value = std::move(value); }
private:
T _value;
};
class Angle
{
public:
Angle(const Member<float>& x, const Member<float>& y) :
_x(x), _y(y) {}
operator float() const { return atan2(_y, _x); }
private:
const Member<float>& _x, _y;
};
class Obj
{
public:
Member<float> x, y;
Angle angle;
Obj() : angle(this->x, this->y) {}
};
int main()
{
Obj o;
o.x = 3;
o.y = 5;
std::cout << o.x << ", " << o.y << " -> " << o.angle << std::endl;
}
While other solutions also seem to be possible, this one seems to be the most elegant :P
using namespace std;
struct Vector2 {
float x;
float y;
float init_length = [&]()-> float {return sqrt(x * x + y * y); }();
float init_angle = [&]()-> float {return atan2(y, x); }();
__declspec(property(get = GetAngle, put = SetAngle)) float angle;
__declspec(property(get = GetLength, put = SetLength)) float length;
Vector2() : x(0), y(0) {}
Vector2(float a, float b) : x(a), y(b) {}
~Vector2() {}
Vector2(Vector2& other) : x(other.x), y(other.y) {}
Vector2(Vector2&& other) = delete;
void operator =(Vector2&& other) = delete;
void Display() {
printf("%f\n%f\n%f\n%f\n\n", x, y, length, angle);
}
float GetLength() {
return sqrt(x * x + y * y);
}
float GetAngle() {
return atan2(y, x);
}
void SetLength(float l) {
float a = GetAngle();
x = cos(a) * l;
y = sin(a) * l;
}
void SetAngle(float a) {
float l = GetLength();
x = cos(a) * l;
y = sin(a) * l;
}
};
int main()
{
Vector2 vec = Vector2(10, 17);
vec.Display();
vec.length = 5;
vec.Display();
}

Problem Modifying Eigen Members of a C++ Structure

I have the following C++ structure
struct voxel {
const std::vector<Eigen::ArrayXf>& getVoltage() const { return m_voltage; }
const std::vector<int>& getChannelIndex() const { return m_channelIndex; }
float getx() { return m_x; }
float gety() { return m_y; }
float getz() { return m_z; }
void appendVoltage(Eigen::ArrayXf v) { m_voltage.push_back(v); }
void appendChannelIndex(int c) { m_channelIndex.push_back(c); }
void setPosition(float x, float y, float z) { m_x = x; m_y = y; m_z = z; }
void change(int c) { m_voltage.at(c)(0) = -100; std::cout << m_voltage.at(c) << "\n"; }
private:
std::vector<Eigen::ArrayXf> m_voltage;
std::vector<int> m_channelIndex;
float m_x;
float m_y;
float m_z;
};
An array of the above structure is used in the following class
class voxelBuffer {
public:
std::vector<voxel> voxels;
voxel getVoxel(ssize_t voxelId) { return voxels.at(voxelId); };
const std::vector<Eigen::ArrayXf>& getVoltage2(ssize_t voxelId) const { return voxels.at(voxelId).getVoltage(); };
ssize_t getNumVoxels() { return voxels.size(); }
};
As an example:
voxel vx1;
vx1.setPosition(1.1, 2.1, 3.1);
vx1.appendChannelIndex(1);
vx1.appendVoltage(Eigen::ArrayXf::LinSpaced(10, 0.0, 10 - 1.0));
vx1.appendChannelIndex(2);
vx1.appendVoltage(Eigen::ArrayXf::LinSpaced(20, 0.0, 20 - 1.0));
vx1.appendChannelIndex(3);
vx1.appendVoltage(Eigen::ArrayXf::LinSpaced(30, 0.0, 30 - 1.0));
voxelBuffer vxbuffer;
vxbuffer.voxels.push_back(vx1);
I try to change the first array of voxel
vxbuffer.getVoxel(0).change(0);
std::cout << vxbuffer.getVoltage2(0).at(0) << "\n";
But the element is still not modified. Could someone please help me with this issue?
vxbuffer.getVoxel(0) is not returning a reference to the voxel in the container. You are returning a copy of it, because your return type of voxel getVoxel(ssize_t voxelId) is voxel, not voxel&.
Then you call .change(0) on that temporary object of type voxel, not on the voxel object in the container.

Class square finding of axis

I am trying to figure out how to find the axis of class Square's axis as shown below? But I've been trying for hours and still did not managed to solve it. Can someone with their high level expertise show me the ropes to do it? Because both center function call and axis function call in main() does call the same x() and y(), hence brought me to a state of confusion. I know the inheritance of square from circle is weird. But it is what my school wants. Note: Main() CANNOT be modified! Thanks!
Output:
Square::axis test failed
8.87627 0.284967
3.82567 0.958537
Tests passed: 50%
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
class Object
{
public:
private:
float d;
public:
Object(float n) : d(n){}
Object(){}
float depth() const
{
return d;
}
struct PointType
{
float x2;
float y2;
PointType( float x1, float y1) :x2(x1),y2(y1){}
PointType(){}
float x()
{
return x2;
}
float y()
{
return y2;
}
PointType center()
{
return *this;
}
};
struct VectorType
{
float tx;
float ty;
VectorType( float tx1, float ty1) :tx(tx1),ty(ty1){}
VectorType( ){}
};
virtual ~Object()
{}
};
class Point :public Object
{
private:
PointType mpoint;
public:
Point(const PointType& pt, float& y1) :Object(y1), mpoint(pt) {}
Point(const PointType& pt):mpoint(pt){}
Point(){}
Point center() const
{
return *this;
}
float x()
{
return mpoint.x2;
}
float y()
{
return mpoint.y2;
}
virtual ~Point(){}
};
class Circle : public Point
{
private:
Object::PointType m_pt;
float r;
public:
Circle(const PointType pts, float rad, float dep)
: Point(m_pt,dep),m_pt(pts),r(rad) {}
Circle(const PointType pts, float rad):m_pt(pts),r(rad){}
Circle(){}
float radius() const
{
return r;
}
Circle center() const
{
return *this;
};
float x()
{
return m_pt.x2;
}
float y()
{
return m_pt.y2;
}
};
class Square: public Circle
{
private:
Object::PointType s_pt;
Object::VectorType v_pt;
float a=getRadius();
public:
Square(const PointType spts,const VectorType vpts,float depth) :
Circle(spts,a,depth),s_pt(spts),v_pt(vpts){}
Square(const Object::PointType& spts, const VectorType vpts):s_pt(spts),v_pt(vpts){}
Square axis() const
{
return Square(s_pt,v_pt,getRadius());
}
Square center() const
{
return *this;
}
float radius() const
{
return a;
}
float getRadius() const
{
float rad= sqrt(v_pt.tx * v_pt.tx + v_pt.ty * v_pt.ty);
return rad;
}
float x() const
{
return s_pt.x2;
// v_pt.tx/radius();
}
float y() const
{
return s_pt.y2;
// v_pt.ty/radius();
}
};
const float EPSILON = 1e-5f;
bool is_near(float x, float y)
{
return std::abs(x - y) < EPSILON;
}
float frand()
{
return 10.0f * float(rand()) / float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0;
int max_count = 0;
float x = frand();
float y = frand();
float sx = frand();
float sy = frand();
float depth = frand();
Square square(Square::PointType(x, y), Square::VectorType(sx, sy), depth);
if (is_near(square.center().x(), x) &&
is_near(square.center().y(), y))
{
++count;
}
else
{
std::cout << " - Square::center test failed" << std::endl;
}
++max_count;
float radius = std::sqrt(sx * sx + sy * sy);
if (is_near(square.axis().x(), sx / radius) &&
is_near(square.axis().y(), sy / radius))
{
++count;
}
else
{
std::cout << " - Square::axis test failed" << std::endl;
}
++max_count;
std::cout << square.axis().x()<< " " << sx / radius<<std::endl;
std::cout << square.axis().y()<< " " << sy / radius<<std::endl;
int result = static_cast<int>(
100.0f * static_cast<float>(count) / static_cast<float>(max_count) + 0.5f
);
std::cout << "Tests passed: " << result << "%" << std::endl;
return result;
}

How to make a good set/get method

For example, we have this class:
class Coord
{
double x;
double y;
double z;
public:
Coord() { x = y = z = 0; }
void set(double xx, double yy, double zz)
{
x = xx;
y = yy;
z = zz;
}
void set_x(double xx) { x = xx; }
void set_y(double yy) { y = yy; }
void set_z(double zz) { z = zz; }
double get_x() { return x; }
double get_y() { return y; }
double get_z() { return z; }
};
On these 7 methods we can set and get x,y and z of a coordinate. I am interested in create less methods set() and get() where I can call something like that:
int main()
{
Coord c;
c.set_x(5); /* only set x */
c.set_y(6); /* or y */
c.set_z(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get_x(); /* only get x */
c.get_y(); /* or y */
c.get_z(); /* or z */
}
If the Coord class is that simple, it could also be a struct.
Anyway you can write something like:
class Coord
{
public:
enum xyz {x = 0, y, z};
Coord() : vec{x, y, z} {}
template<xyz C> void set(double v) { vec[C] = v; }
template<xyz C> double get() const { return vec[C]; }
void set(double xx, double yy, double zz)
{
set<Coord::x>(xx);
set<Coord::y>(yy);
set<Coord::z>(zz);
}
private:
double vec[z + 1];
};
and use the class this way:
Coord c;
c.set<Coord::x>(5); /* only set x */
c.set<Coord::y>(6); /* or y */
c.set<Coord::z>(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get<Coord::x>(); /* only get x */
c.get<Coord::y>(); /* or y */
c.get<Coord::z>(); /* or z */
getters and setters are meant to protect your data and provide encapsulation.
For example they allow you to add side effects to getting and setting operations (such as writing to a log), or allow you to catch invalid values early before they cause horrible problems later (For example preventing values greater than n being set).
Here's a brief and contrived setter example:
void set_x(int x)
{
// prevent an invalid value for x
if( x > 11 ) x = 11;
// set x
this.x = x;
// log the operation
log("user set x to {0}", x);
}
Assuming your c.set.x(5) example is not using some whacky preprocessor macros, it would require that the Coord class have a member variable called set with methods
x()
y()
z()
This would require just as much code as writing a set_x(), set_y() and set_z() method in your Coord class, but the methods would not belong to the class Coord, instead belonging to another class that is itself used as a member variable of Coord. Doing so would not really make any logical sense... the x, y, and z values belong to Coord and operations on them are operations on the Coord.
Furthermore the methods x() y() and z() would no longer obey the general principle of making methods verbs. Anyone reading the class with those methods would have no idea what function z() is supposed to do!
It would also create a refactoring nightmare: If for example in the future a business requirement appeared that meant no Coords could ever have values of x greater than 21 somone maintaining your code would have to change a class that is a member of Coord rather than the Coord class itself.
Encapsulation with getter and setter methods is often a really good idea and in C++ with the benefit of inlining it can even add no runtime overhead. But keep to the principle "Make everything as simple as possible, but not simpler." In other words get_x() and set_x() are widely understood, useful, easily refactored, convenient, self-documenting and performant... other approaches are likely to be less so.
First: Your usage of c.set.x would not work because you would call a public element set on your object c and where set has a public element x.
I find both classes lack standards of clean code and usual style of getter and setter - even without specifying any language.
A usual way would be to create the following:
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
void setX(double x) { this.x = x; }
void setY(double y) { this.y = y; }
void setZ(double z) { this.z = z; }
double getX() { return x; }
double getY() { return y; }
double getZ() { return z; }
};
Though some prefer to use m_x as setter variable parameter or any other convention.
Anyhow everyone would directly understand your code. Is able to set and get coordinate values for x, y, z and it would look pretty standard-default-behaviour if someone does following:
Coord P(10, 15, 20);
std::cout << P.getX() << " " << P.getY() << std::endl;
P.setX(-10);
P.setZ(40);
You've already gotten some good answers, but you could also use an enum if you really want a syntax with fewer setters and getters. The client syntax can get a little clunky and awkward, but it of course depends on what you're looking for!
#include <iostream>
class Coord {
public:
enum Axis {
X = 0,
Y,
Z,
NUM_AXES
};
// Using extended initializer lists (C++11)
Coord() : axes_{0, 0, 0} {}
Coord(double x, double y, double z) : axes_{x, y, z} {}
void set(Axis a, double d) {
axes_[a] = d;
}
double get(Axis a) const {
return axes_[a];
}
private:
double axes_[NUM_AXES];
// Copy constructor and assgn. operator included for good measure
Coord(const Coord &);
void operator=(const Coord &);
};
int main()
{
Coord c(1, 2, 3);
std::cout << "X: " << c.get(Coord::X) << std::endl;
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
std::cout << "Z: " << c.get(Coord::Z) << std::endl;
c.set(Coord::Y, 4);
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
return 0;
}
This strange code does exactly what you ask - just C++ fun. Don't do this!
#include <iostream>
using namespace std;
class Coord {
double x;
double y;
double z;
public:
class Setter {
public:
Setter(Coord& coord) : c(coord) {}
void x(double value) { c.x = value; }
void y(double value) { c.y = value; }
void z(double value) { c.z = value; }
void operator()(double x, double y, double z) { c.x = x; c.y = y; c.z = z; }
private:
Coord& c;
};
class Getter {
public:
Getter(Coord& coord) : c(coord) {}
double x() { return c.x; }
double y() { return c.y; }
double z() { return c.z; }
private:
Coord& c;
};
Setter set;
Getter get;
Coord() : set(*this), get(*this) { x = y = z = 0; }
friend class Setter;
};
int main()
{
Coord c;
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set.x(1);
c.set.y(2);
c.set.z(3);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set(5, 6, 7);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
return 0;
}
Output:
0 0 0
1 2 3
5 6 7
The more or less standard way to expose this, if validation is not a concern, is to return mutable references from the non-const accessor, and values from the const one. This allows you to separate the interface from storage, while not making the syntax too heavy.
private:
double m_x, m_y, m_z;
public:
double & x() { return m_x; }
double & y() { return m_y; }
double & z() { return m_z; }
double x() const { return m_x; }
double y() const { return m_y; }
double z() const { return m_z; }
This will allow c.x() to obtain the value of the x coordinate whether the Coord object is const or not, and allows setting the value using the syntax c.x() = value.
In the interest of completeness, you can get exactly the syntax you want using the following code, but I would strongly recommend against it. It is a lot of extra code, provides no real benefit, and creates a syntax that is uncommon and most programmers will not find it intuitive.
The technique creates two nested classes getters and setters and exposes instances of them as public members of Coord.
This is provided as an example of how to achieve the result you asked for, but I do not recommend this approach.
class Coord
{
private:
double x, y, z;
public:
Coord();
Coord(double, double, double);
class setters {
friend class Coord;
private:
explicit setters(Coord &);
public:
setters(setters const &) = delete;
setters & operator=(setters const &) = delete;
void x(double) const;
void y(double) const;
void z(double) const;
private:
Coord & coord;
};
friend class setters;
class getters {
friend class Coord;
private:
explicit getters(Coord const &);
public:
getters(getters const &) = delete;
getters & operator=(getters const &) = delete;
double x() const;
double y() const;
double z() const;
private:
Coord const & coord;
};
friend class getters;
setters const set;
getters const get;
};
Coord::Coord() : x(0), y(0), z(0), set(*this), get(*this) { }
Coord::Coord(double px, double py, double pz) : x(px), y(py), z(pz), set(*this), get(*this) { }
Coord::setters::setters(Coord & c) : coord(c) { }
void Coord::setters::x(double px) const {
coord.x = px;
}
void Coord::setters::y(double py) const {
coord.y = py;
}
void Coord::setters::z(double pz) const {
coord.z = pz;
}
Coord::getters::getters(Coord const & c) : coord(c) { }
double Coord::getters::x() const {
return coord.x;
}
double Coord::getters::y() const {
return coord.y;
}
double Coord::getters::z() const {
return coord.z;
}
(Demo)
Actually the function can be reduce based on your requirement as follows,
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
void GetValues(double* x=NULL, double* y=NULL, double* z=NULL);
void SetValues(double x=0, double y=0, double z=0)
/* You can use constructors like below to set value at the creation of object*/
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
/*You can set the values of x, y & z in a single function as follows. It can be used at any time without restriction */
void SetValues(double x, double y, double z)
{
if(x > 0) //It is optional to use condition so that you can update any one variable aloen by sending other two as ZERO
{
this.x = x;
}
if(y > 0)
{
this.y = y;
}
if(z > 0)
{
this.z = z;
}
}
/*You can Get the values of x, y & z in a single function as follows. Pass By Reference id the concept you need */
void GetValues(double* x, double* y, double* z)
{
if(x != NULL) //It x is not null.
{
x = this.x;
}
if(y != NULL)
{
y = this.y;
}
if(z != NULL)
{
z= this.z;
}
}
};
while calling you can call like the following,
SetValues(10, 20, 0); //To set x and y values alone.
double x1 = 0;double y1 = 0;double z1 = 0;
GetValues(&x1, &y1, &z1)//It will return the values x1 y1 and z1 as 10, 20 & 0
You cannot do exactly what you want.
In
c.set.x(5); /* only set x */
the c.set subexpression is retrieving a field set from c (unless set is a #define-d macro, but that would be silly).

What is wrong with the following C++ class?

So, basically I created a Float class to track down the range of floating point values used in the program. I just replace float in my program with Float. However, the output of my program changes when I use this class, but I can't figure out where is the problem.
#define real float
class Float
{
private:
real data;
static real minVal;
static real maxVal;
static void updateMinMax( real x )
{
if ( x < minVal )
minVal = x;
if ( x > maxVal )
maxVal = x;
}
public:
static real getMin()
{
return minVal;
}
static real getMax()
{
return maxVal;
}
Float()
{
data = 0;
}
Float(real x)
{
data = x;
updateMinMax(data);
}
void setFloat( real x )
{
data = x;
updateMinMax(data);
}
void setMaxOf( real x, real y )
{
data = (x > y)? x : y;
updateMinMax(data);
}
void setInt( int x )
{
data = x;
updateMinMax(data);
}
real getFloat() const
{
return data;
}
operator int() const { return (int)data; }
void operator=(Float x)
{
data = x.data;
updateMinMax( data );
}
Float operator+(const Float& x) const
{
updateMinMax( data + x.data );
return Float(data + x.data);
}
void operator+=(Float x)
{
data += x.data;
updateMinMax( data );
}
Float operator-(const Float& x) const
{
updateMinMax( data - x.data );
return Float(data - x.data);
}
Float operator-() const
{
updateMinMax( -data );
return Float(-data);
}
void operator-=(Float x)
{
data -= x.data;
updateMinMax( data );
}
Float operator*(const Float& x) const
{
updateMinMax( data * x.data );
return Float(data * x.data);
}
void operator*=(Float x)
{
data *= x.data;
updateMinMax( data );
}
Float operator/(const Float& x) const
{
updateMinMax( data / x.data );
return Float(data / x.data);
}
void operator/=(Float x)
{
data /= x.data;
updateMinMax( data );
}
bool operator<(const Float& x) const
{
return data < x.data;
}
bool operator<=(const Float& x) const
{
return data <= x.data;
}
bool operator>(const Float& x) const
{
return data > x.data;
}
bool operator>=(const Float& x) const
{
return data >= x.data;
}
bool operator==(const Float& x) const
{
return data == x.data;
}
friend ostream& operator<<(ostream& o, Float& x)
{
o << x.data;
return o;
}
friend istream& operator>>(istream& i, Float& x)
{
i >> x.data;
return i;
}
};
The following test program demonstrates at least one difference between using a float and your Float class:
void test(float x)
{
cout<<"Called with float argument"<<endl;
}
void test(int x)
{
cout<<"Called with int argument"<<endl;
}
int main() {
Float arg1;
float arg2;
test(arg1);
test(arg2);
return 0;
}
Output:
Called with int argument
Called with float argument