A job for lambda expressions?

R

Rune Allnor

Hi all.

I am working on an application to process geometric (x,y,z) data
measured in a physical world. The application relies heavily on
the user interacting with the data through a GUI.

In particular, both the 'world data' and the 'screen data' require
much the same types of operations:

- Select bounding polygons.
- Preprocess / regularize the polygons.
- Identify whether data points are enclosed or not, by the polygon.

The algorithms in both cases are the same. The semantics differ.
For instance, my xyzpoint<T> class addresses the x coordinate
of the individual point p as

xyzpoint<float> p;
float x = p.x();

whereas the Qt GUI library addresses the x coordinate of a point
on the screen as something like

QGraphicsItem *item = new SomeGraphicsItem;
item->pos().x();

So I would save a lot of duplicate work if I could somehow introduce
the exact semantics of addressing the individual coordinates of the
data points as variables.

Could lambda expressions be used for this?
Or are there other ways to achieve the same end?

Rune
 
M

Marcel Müller

Hi,

Rune said:
So I would save a lot of duplicate work if I could somehow introduce
the exact semantics of addressing the individual coordinates of the
data points as variables.

Could lambda expressions be used for this?
Or are there other ways to achieve the same end?

there are a several possibilities, since the number of different cases
are limited.

- Use a function pointer to retrieve the desired information.
(Only if you are context free.)

- Use an interface with the desired methods.
The implementing class could carry the context.

- Use templates and functors.
This has the advantage of almost no runtime overhead and is in fact
the base of lambda expressions.


If I had the choice, I would prefer the second solution unless the
performance becomes undesirable.


Marcel
 
R

Rune Allnor

Hi,




there are a several possibilities, since the number of different cases
are limited.

- Use a function pointer to retrieve the desired information.
   (Only if you are context free.)

- Use an interface with the desired methods.
   The implementing class could carry the context.

- Use templates and functors.
   This has the advantage of almost no runtime overhead and is in fact
   the base of lambda expressions.

If I had the choice, I would prefer the second solution unless the
performance becomes undesirable.

While performance questions might be more or less irrelevant
in the case of GUI interaction, they *are* an issue when
processing the measured data.

Rune
 
M

Marcel Müller

Rune said:
While performance questions might be more or less irrelevant
in the case of GUI interaction, they *are* an issue when
processing the measured data.

Sure, but it depends on what you are doing with the returned data. If
there are several dozen math operations with each data point in avarage,
then the additional function call will not harm significantly.

On the other side, if you call these functions over and over, the
overhead may be harmful.


Marcel
 
A

Anthony Delroy

...
The algorithms in both cases are the same. The semantics differ.
For instance, my xyzpoint<T> class addresses the x coordinate
of the individual point p as

xyzpoint<float> p;
float x = p.x();

whereas the Qt GUI library addresses the x coordinate of a point
on the screen as something like

QGraphicsItem *item = new SomeGraphicsItem;
item->pos().x();

So I would save a lot of duplicate work if I could somehow introduce
the exact semantics of addressing the individual coordinates of the
data points as variables.

Could lambda expressions be used for this?
Or are there other ways to achieve the same end?

Perhaps I'm missing something... what's wrong with the obvious?

inline float get_x(QGraphicsItem* p) { return p->pos().x(); }
inline float get_x(xyzpoint<float>& xyz) { return xyz.x(); }

Cheers,
Tony
 
R

Rune Allnor

Perhaps I'm missing something... what's wrong with the obvious?

    inline float get_x(QGraphicsItem* p) { return p->pos().x(); }
    inline float get_x(xyzpoint<float>& xyz) { return xyz.x(); }

First of all that my algorithm library needs to be aware
of the various types of points it might have to work on.
I'd prefer it not to.

Second, an issue I have not mentioned here - that in the
data analysis application the algorithms might have to
work along different dimensions. Some times one needs to
work in the (x,y) plane. At other times one needs to work
in the (y,z) or (x,z) planes. There are too many possible
uses to individually implement each one specifically. And
once one have done it for the data analysis application,
one really would like to benefit from all that hard work
when one needs the same functionality in a 'mere' GUI.

A nifty way of parametrizing the coordinate access methods,
that did not introduce additional run-time overhead, would
work wonders.

After having browsed a few books and pages, it seems that
I need much the same functionality that boost::bind offers.
Or am I wrong?

Rune
 
A

Anthony Delroy

First of all that my algorithm library needs to be aware
of the various types of points it might have to work on.
I'd prefer it not to.

Your algorithms don't have to be aware. Consider:

#include <iostream>

class Point1
{
public:
Point1(int x, int y) : x_(x), y_(y) { }

int x() const { return x_; }
int y() const { return y_; }

friend std::eek:stream& operator<<(std::eek:stream& os, const Point1& p)
{
return os << '(' << p.x_ << ',' << p.y_ << ')';
}

private:
int x_, y_;
};

class Point2
{
public:
Point2(int x, int y) : x_(x), y_(y) { }

int get_x() const { return x_; }
int get_y() const { return y_; }

private:
int x_, y_;
};

inline int get_x(const Point1& p1) { return p1.x(); }
inline int get_x(const Point2* p_p2) { return p_p2->get_x(); }
inline int get_y(const Point1& p1) { return p1.y(); }
inline int get_y(const Point2* p_p2) { return p_p2->get_y(); }

template <typename PointA, typename PointB>
Point1 mid(const PointA& a, const PointB& b)
{
return Point1((get_x(a) + get_x(b)) / 2, (get_y(a) + get_y(b)) /
2);
}

int main()
{
Point1 p1(1, 3);
Point2* p2 = new Point2(5, 9);
std::cout << mid(p1, p2) << '\n';
}

Another alternative is to template the algorithm with a policy
specifying how to access the points:

template <class Point, class Access>
void algo(...)
{
... Access::get_x(my_point) ...
}

(Good idea to read Modern C++ Design by Andrei Alexandrescu if you
haven't already.)

These are all compile time adaptations.
Second, an issue I have not mentioned here - that in the
data analysis application the algorithms might have to
work along different dimensions. Some times one needs to
work in the (x,y) plane. At other times one needs to work
in the (y,z) or (x,z) planes. There are too many possible
uses to individually implement each one specifically. And
once one have done it for the data analysis application,
one really would like to benefit from all that hard work
when one needs the same functionality in a 'mere' GUI.

A nifty way of parametrizing the coordinate access methods,
that did not introduce additional run-time overhead, would
work wonders.

After having browsed a few books and pages, it seems that
I need much the same functionality that boost::bind offers.
Or am I wrong?

I haven't got my head around how you might want to access these
planes, so am not sure.

Cheers,
Tony
 
R

Rune Allnor

I haven't got my head around how you might want to access these
planes, so am not sure.

All you need to do is to decide which of the coordinates
is the ordinate and which is the abscissa. In the (x,y)
case you use x as the ordinate and y as the abscissa.
In the (y,z) case you use y as the ordinate and z as the
abscissa, and so on. Apart from that, all the algorithms
are the same.

What one needs is the internal functions

T ordinate(const point_t&);
T abscissa(const point_t&);

that can be called on each element (preferably with the
element staying oblivious to the context), and a way to
overload the implementations of those functions. And an
as loose way as possible to couple the implementation to
the point classes in question.

As far as I can tell - which isn't very far - it's the
same mechanism (whichever mechanism that might be) that
is required to flip the ordinate-abscissa pair for a given
class of points, as is needed to specify the implementation
of the ordinate/abscissa access functions for some other
class of points.

Coming to think of it, it seems an interface along the
lines of

template<class T, class point_t, class result_t>
result_t& process_data(std::vector<point_t>,
T ordinate(const point_t&),
T abscissa(const point_t&));

where one could use boost::bind to specify the ordinate
and abscissa access functions, might be what I am looking
for...

Rune
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top