c++ avoid code duplication operator overloading - c++

My Question is the following, let's say I have this classes:
class ID3OBJ
{
public:
const double X;
const double Y;
const double Z;
ID3OBJ(double x, double y, double z);
ID3OBJ();
const ID3OBJ operator+ (const ID3OBJ param) const;
}
class Vector : public ID3OBJ
{
public:
Vector(double x, double y, double z);
Vector();
/*const Vector const operator+ (const Vector param); */
}
class Point : public ID3OBJ
{
public:
Point(double x, double y, double z);
Point();
}
class Plane : public ID3OBJ
{
public:
Point Origin;
Vector Direction1;
Vector Direction2;
Vector NormalVector;
Plane(Point Origin, Vector Normalvector);
Plane(Point Origin, Vector Direction1, Vector Direction2);
Plane();
}
class D3GON : public ID3OBJ, public Plane
{
public:
std::vector<Point> EdgePoints;
D3GON(Point P1, Point P2, Point P3);
};
In my current code I have to redefine the operator overload for each class, how can I avoid this code-duplication?
Do I have to add convert-functions?
I use const member-values, to deny objects changes after creation. Meaning if any low-level object has to be changed it has to be replaced by a new one. See my operator overload below:
// operator overwrites:
const ID3OBJ ID3OBJ::operator+ (const ID3OBJ param) const { double newX, newY, newZ; newX = X + param.X; newY = Y + param.Y; newZ = Z + param.Z; return ID3OBJ(newX, newY, newZ); }
Thank you :)

The Curiously recurring template pattern is the way to go here. It is slightly more complex because you want multiple derivation levels. But here is a code example:
template <class T>
class ID3OBJ
{
public:
double X,Y,Z;
T operator+(const T& obj) const {
T t;
t.X = X + obj.X;
t.Y=Y+obj.Y;
t.Z=z+obj.Z;
return t;
}
};
class Vector : public ID3OBJ<Vector>
{
public:
// some stuff
};
class Point : public Vector, public ID3OBJ<Point>
{
public:
// X, Y and Z exist twice, once in Vector, once in ID3OBJ<Point>, so we must disambiguate
using ID3OBJ<Point>::X;
using ID3OBJ<Point>::Y;
using ID3OBJ<Point>::Z;
};
You can add Vector (and you'll get Vector) or just Point and you'll get Point. More interestingly, if you add Point and Vector, you get an Vector result because the overloaded operator + resolution will select Vector::operator +

Related

error C2248: 'point::x': cannot access private member declared in class 'point'

With this code:
#include <iostream>
using namespace std;
class point{
public:
double get_x();
void set_x(double v);
double get_y();
void set_y(double z);
private:
double x, y;
};
point operator+(point& p1, point& p2)
{
point sum = {p1.x};// + p2.x, p1.y + p2.y};
return sum;
}
int main()
{
point a = {3.5,2.5}, b = {2.5,4.5}, c;
}
I get the following compiler errors saying the private members cannot be accessed:
point.cpp(22): error C2248: 'point::x': cannot access private member declared in class 'point'
point.cpp(17): note: see declaration of 'point::x'
point.cpp(8): note: see declaration of 'point'
I am pretty new to C++ and can't seem to figure out how to resolve this issue. Any help is much appreciated.
You declared x and y as private so they can't be accessed in that function(or outside the class) unless you make that function a friend of the class, but if you want to overload the + operator, you should do it inside the class, something like this :
class point
{
public:
point(double x, double y) // CONSTRUCTOR
:x(x), y(y)
{
}
double get_x() const{
return x;
};
void set_x(double v)
{
x = v;
};
double get_y() const{
return y;
};
void set_y(double z)
{
y = z;
};
point operator+(const point &obj)
{
double newX = this->x + obj.get_x();
double newY = this->y + obj.get_y();
point sum{newX, newY};
return sum;
};
private:
double x, y;
};

Is there a way to compound functions in C++?

General question :
If there are two objects A and B with respective functions f_A(arg list) and f_B(arg list).
What's the best way to create an object C with a function compounded of f_A(...) and f_B(...) ?
for example : f_C() = f_A() + f_B() or f_C() = f_A(f_B())
Is it possible to overload the "+" operator such that we can create the object C doing something like that ?
auto object_c = object_a + object_b
Here is a sample of my code :
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
)
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
GaussianKernel operator+(const GaussianKernel& b) {
/*Here I would like to overload the + operator such that
I can create a kernel from two others kernels,
I mean with a covariance function compound of the previous ones
*/
}
private:
double m_sigma;
double m_scale;
};
Thanks you.
Given two methods f_A and f_B you can get f_C returning the sum of the others by using for example a lambda:
auto f_C = [](/*param*/){ return f_A(/*param*/) + f_B(/*param*/); };
auto sum_result = f_C(param);
To get the compound method it would be this:
auto f_C = [](/*param*/){ return f_B( f_A(/*param*/)); };
auto compound_result = f_C(param);
PS: I know that this is not directly applicable to your example, still trying to find out what exactly you want to do.
I would start with prototype solution like this:
class FooKernel : public Kernel {
public:
FooKernel (std::function<double(double, double)> fun) : fun_(fun) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
std::function<double(double, double)> fun_;
};
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
double covarianceFunction(
double X,
double Y
) const
{
double result;
result = m_scale * exp(-norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T &b) const {
return FooKernel([b, this](double X, double Y){
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
private:
double m_sigma;
double m_scale;
};
No longer lambdas are used, but now uses Your function as You wished.
Later on I would try to remove the std::function as it may have quite big performance impact. Instead I would make the FooKernel a class template, that stores callable by value.
I would suggest another subclass of Kernel:
class CompoundGaussianKernel : public Kernel {
public:
CompoundGaussianKernel(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
: m_kernel1(kernel1), m_kernel2(kernel2)
{}
double covarianceFunction(double X, double Y)
{
return m_kernel1.covarianceFunction(X, Y) + m_kernel2.covarianceFunction(X, Y);
// or any other composition than "+"
}
private:
GaussianKernel m_kernel1;
GaussianKernel m_kernel2;
};
I recommend not to define operator+ inside of a class but as a free function.
CompoundGaussianKernel operator+(GaussianKernel const& kernel1, GaussianKernel const& kernel2)
{
return CompoundGaussianKernel(kernel1, kernel2);
}

C++: How to make a object (class) with two brackets. for ex Point obj1((2,2),(3,8))

I have this code
class Point
{
private:
float x,y;
public:
Point(const float _x,const float _y)
{
x=_x;
y=_y;
}
~Point(){};
};
class triangle
{
private:
Point *objPOA;
Point *objPOB;
Point *objPOC;
public:
triangle(const float a,const float b,const float c,const float d,const float e,const float f)
{
objPOA=new Point(a,b);
objPOB=new Point(c,d);
objPOC=new Point(e,f);
}
~triangle()
{
delete objPOA;
delete objPOB;
delete objPOC;
}
};
I want to make this
int main()
{
triangle obj((1,2),(2,5),(8,6));
return 0;
}
It can be done;
I mean inside obj parameters include brackets.
This can be done without brackets but i want to know if it is possible with brackets.
You can make your triangle constructor take 3 Points
triangle(const Point& p1, const Point& p2, const Point& p3):
objPOA(p1), objPOB(p2), objPOC(p3) {}
and instead of pointers define in your class regular objects of type Point
Point objPOA, objPOB, objPOC;
You can then use the { } to initialize Points in the constructor of the triangle as
triangle obj({1,2},{2,5},{8,6});
because Point is an aggregate. In C++11 the above syntax is valid even if Point is a non-aggregate, due to the new uniform initialization syntax.

C++0x Designated Initializers

I could find a way to do Designated Initializers in C++0x with only one member initializing.
Is there a way for multiple member initializing ?
public struct Point3D
{
Point3D(float x,y) : X_(x) {}
float X;
};
I want :
public struct Point3D
{
Point3D(float x,y,z) : X_(x), Y_(y), Z_(z) {}
float X_,Y_,Z_;
};
You have a few mistakes in your constructor, here is how you should write it:
/* public */ struct Point3D
// ^^^^^^
// Remove this if you are writing native C++ code!
{
Point3D(float x, float y, float z) : X_(x), Y_(y), Z_(z) {}
// ^^^^^ ^^^^^
// You should specify a type for each argument individually
float X_;
float Y_;
float Z_;
};
Notice, that the public keyword in native C++ has a meaning which is different from the one you probably expect. Just remove that.
Moreover, initialization lists (what you mistakenly call "Designated Initializers") are not a new feature of C++11, they have always been present in C++.
#Andy explained how you should be doing this if you're going to define your own struct.
However, there is an alternative:
#include <tuple>
typedef std::tuple<float, float, float> Point3D;
and then define some function as:
//non-const version
float& x(Point3D & p) { return std::get<0>(p); }
float& y(Point3D & p) { return std::get<1>(p); }
float& z(Point3D & p) { return std::get<2>(p); }
//const-version
float const& x(Point3D const & p) { return std::get<0>(p); }
float const& y(Point3D const & p) { return std::get<1>(p); }
float const& z(Point3D const & p) { return std::get<2>(p); }
Done!
Now you would use it as:
Point3D p {1,2,3};
x(p) = 10; // changing the x component of p!
z(p) = 10; // changing the z component of p!
Means instead of p.x, you write x(p).
Hope that gives you some starting point as to how to reuse existing code.

"Retroactive Union" - can it be done?

I've got two classes: a template class, and a regular class that inherits from it:
template <int N> class Vector
{
float data[N];
//etc. (math, mostly)
};
class Vector3 : public Vector<3>
{
//Vector3-specific stuff, like the cross product
};
Now, I'd like to have x/y/z member variables in the child class (full members, not just getters - I want to be able to set them as well). But to make sure that all the (inherited) math works out, x would have to refer to the same memory as data[0], y to data[1], etc. Essentially, I want a union, but I can't declare one in the base class because I don't know the number of floats in the vector at that point.
So - can this be done? Is there some sort of preprocessor / typedef / template magic that will achieve what I'm looking for?
PS: I'm using g++ 4.6.0 with -std=c++0x, if that helps.
Edit: While references would give the syntax I'm looking for, the ideal solution wouldn't make the class any bigger (And references do - a lot! A Vector<3> is 12 bytes. A Vector3 with references is 40!).
How about:
class Vector3 : public Vector<3>
{
public:
// initialize the references...
Vector3() : x(data[0]), y(data[1]), z(data[2]){}
private:
float& x;
float& y;
float& z;
};
Of course, if you want them to occupy the same space, then that's a different story...
With a little template magic, you can do the following...
#include <iostream>
template <int N, typename UnionType = void*> struct Vector
{
union
{
float data[N];
UnionType field;
};
void set(int i, float f)
{
data[i] = f;
}
// in here, now work with data
void print()
{
for(int i = 0; i < N; ++i)
std::cout << i << ":" << data[i] << std::endl;
}
};
// Define a structure of three floats
struct Float3
{
float x;
float y;
float z;
};
struct Vector3 : public Vector<3, Float3>
{
};
int main(void)
{
Vector<2> v1;
v1.set(0, 0.1);
v1.set(1, 0.2);
v1.print();
Vector3 v2;
v2.field.x = 0.2;
v2.field.y = 0.3;
v2.field.z = 0.4;
v2.print();
}
EDIT: Having read the comment, I realise what I posted before was really no different, so a slight tweak to the previous iteration to provide direct access to the field (which is what I guess you are after) - I guess the difference between this and Rob's solution below is that you don't need all the specializations to implement all the logic again and again...
How about template specialization?
template <int N> class Vector
{
public:
float data[N];
};
template <>
class Vector<1>
{
public:
union {
float data[1];
struct {
float x;
};
};
};
template <>
class Vector<2>
{
public:
union {
float data[2];
struct {
float x, y;
};
};
};
template <>
class Vector<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.x;
v3.data[1];
};
EDIT Okay, here is a different approach, but it introduces an extra identifier.
template <int N> class Data
{
public:
float data[N];
};
template <> class Data<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
template <int N> class Vector
{
public:
Data<N> data;
float sum() { }
float average() {}
float mean() {}
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.data.x = 0; // Note the extra "data".
v3.data.y = v3.data.data[0];
};
Here's one possibility, cribbed from my answer to this question:
class Vector3 : public Vector<3>
{
public:
float &x, &y, &z;
Vector3() : x(data[0]), y(data[1]), z(data[2]) { }
};
This has some problems, like requiring you to define your own copy constructor, assignment operator etc.
You can make the following:
template <int N> struct Vector
{
float data[N];
//etc. (math, mostly)
};
struct Vector3_n : Vector<3>
{
//Vector3-specific stuff, like the cross product
};
struct Vector3_a
{
float x, y, z;
};
union Vector3
{
Vector3_n n;
Vector3_a a;
};
Now:
Vector3 v;
v.n.CrossWhatEver();
std::cout << v.a.x << v.a.y << v.a.z
You could try the anonymous union trick, but that is not standard nor very portable.
But note that with this kind of union it is just too easy to fall into undefined behaviour without even noticing. It will probably mostly work anyway, though.
I wrote a way a while back (that also allowed getters/setters), but it was such a non-portable garrish hack that YOU REALLY SHOULD NOT DO THIS. But, I thought I'd throw it out anyway. Basically, it uses a special type with 0 data for each member. Then, that type's member functions grab the this pointer, calculate the position of the parent Vector3, and then use the Vector3s members to access the data. This hack works more or less like a reference, but takes no additional memory, has no reseating issues, and I'm pretty sure this is undefined behavior, so it can cause nasal demons.
class Vector3 : public Vector<3>
{
public:
struct xwrap {
operator float() const;
float& operator=(float b);
float& operator=(const xwrap) {}
}x;
struct ywrap {
operator float() const;
float& operator=(float b);
float& operator=(const ywrap) {}
}y;
struct zwrap {
operator float() const;
float& operator=(float b);
float& operator=(const zwrap) {}
}z;
//Vector3-specific stuff, like the cross product
};
#define parent(member) \
(*reinterpret_cast<Vector3*>(size_t(this)-offsetof(Vector3,member)))
Vector3::xwrap::operator float() const {
return parent(x)[0];
}
float& Vector3::xwrap::operator=(float b) {
return parent(x)[0] = b;
}
Vector3::ywrap::operator float() const {
return parent(y)[1];
}
float& Vector3::ywrap::operator=(float b) {
return parent(y)[1] = b;
}
Vector3::zwrap::operator float() const {
return parent(z)[2];
}
float& Vector3::zwrap::operator=(float b) {
return parent(z)[2] = b;
}
To finish off an old question: No. It makes me sad, but you can't do it.
You can get close. Things like:
Vector3.x() = 42;
or
Vector3.x(42);
or
Vector3.n.x = 42;
or even
Vector3.x = 42; //At the expense of almost quadrupling the size of Vector3!
are within reach (see the other answers - they're all very good). But my ideal
Vector3.x = 42; //In only 12 bytes...
just isn't doable. Not if you want to inherit all your functions from the base class.
In the end, the code in question ended up getting tweaked quite a bit - it's now strictly 4-member vectors (x, y, z, w), uses SSE for vector math, and has multiple geometry classes (Point, Vector, Scale, etc.), so inheriting core functions is no longer an option for type-correctness reasons. So it goes.
Hope this saves someone else a few days of frustrated searching!