Imagine you have a simple 2D Point object with two setters and getters.
template <typename T>
class Point
{
public:
Point(T x, T y);
T getX() const;
T getY() const;
void setX(T x);
void setY(T y);
private:
T _x;
T _y;
};
But I want to work with this class in more 'scriptable-like' syntax. Something like :
auto point = Point<double>(10, 10);
point.x = 20;
point.y = point.x + 10;
You will say, just use a struct with public variable :
template <typename T>
struct Point
{
T x;
T y;
};
Yes, but I want to keep the privacy of the parameters and extend the class with some methods. So another idea is to make a wrapper helper that add operator alias to the setters/getters :
template <typename T, typename Get, Get(T::*Getter)() const,
typename Set, void(T::*Setter)(Set)>
struct ReadWrite
{
ReadWrite(T& ptr) : ptr(ptr) {}
inline void operator= (Set const& rhs)
{
(ptr.*Setter)(rhs);
}
inline Get operator()()
{
return (ptr.*Getter)();
}
private:
T& ptr;
};
OK, I just modify my Point class to do the work :
template <typename T>
class Point
{
public:
Point(T x, T y);
T getX() const;
T getY() const;
void setX(T x);
void setY(T y);
private:
T _x;
T _y;
public:
ReadWrite<Point<T>, T, &Point<T>::getX, T, &Point<T>::setX> x;
ReadWrite<Point<T>, T, &Point<T>::getY, T, &Point<T>::setY> y;
};
By adding some arithmetics operators ( + - * / ), I can use it like that:
auto point = Point<double>(10, 10);
point.x = 20;
point.y = point.x + 10;
Here, point.x
is ok in case of operator overloading in the form:
template <typename T, typename V> inline T operator+(ReadWrite<T> const& lhs, V const& rhs) { return lhs() + rhs; }
template <typename T, typename V> inline T operator-(ReadWrite<T> const& lhs, V const& rhs) { return lhs() - rhs; }
template <typename T, typename V> inline T operator*(ReadWrite<T> const& lhs, V const& rhs) { return lhs() * rhs; }
template <typename T, typename V> inline T operator/(ReadWrite<T> const& lhs, V const& rhs) { return lhs() / rhs; }
If I want use this syntax, but without parenthesis on point.x
getter :
auto point = Point<double>(10, 10);
auto x = point.x();
I extend the ReadWrite helper with:
template <typename T, typename Get, Get(T::*Getter)() const,
typename Set, void(T::*Setter)(Set)>
struct ReadWrite
{
ReadWrite(T& ptr) : ptr(ptr) {}
inline void operator= (Set const& rhs)
{
(ptr.*Setter)(rhs);
}
inline Get operator()()
{
return (ptr.*Getter)();
}
inline operator auto() -> Get
{
return operator()();
}
private:
T& ptr;
};
Now with no parenthesis:
double x = point.x; // OK, x is my x value (Point).
auto x = point.x; // Wrong, x is my ReadWrite<T> struct.
What is wrong with the overloading of the auto
operator?
Thank you very much for your answer.