Using transform() in a function

B

Brian McGuinness

I have a question about using the STL transform algorithm in a function.

What I want to do is define a group of array classes to represent
APL-style arrays (arrays in which the number of dimensions and the
length of any dimension can be changed at any time). What I currently
plan is to have an abstract base class at the top, to allow
polymorphism, e.g.:

#include "basedefs.h" // Basic data types, e.g. typedef long Integer

typedef vector<Integer> Dimensions;

class Array {
private:
Dimensions shape;

public:
bool IsScalar() { return shape.empty(); }

...
};

and then have a child template array class so that I can have arrays of
characters, booleans, integers, doubles, and pointers (to support arrays
of arrays). The data would be stored as vector<type>, since Bjarne
Stroustrup does not recommend using valarrays for arrays intended to
vary in size after they are created, with sets of array indices resolved
into single indices into the vector as needed, possibly by implementing
a vector version of gslice and so on.

Now, I want to be able to perform a number of operations on these
arrays, following some simple rules regarding compatible dimensions.
For example, for numeric arrays, I want to be able to add two arrays to
produce a new array. For example, add(a, b) would add corresponding
elements of arrays a and b. I define a function to check if the arrays
have identical dimensions, so we know what elements to match up:

bool Conform (const Array &l, const Array &r) {
return l.shape == r.shape;
}

Then, to support a wide variety of binary operations using the same
shape rules, I would like to do something like this:

Array ScalarDyadic (const Array &l, const Array &r, BinaryFunction op) {
Array a;

if (l.IsScalar()) {
transform (r.start(), r.end(), a.start(), bind1st(op, *l.start()));
}
else if (r.IsScalar()) {
transform (l.start(), l.end(), a.start(), bind2nd(op, *r.start()));
}
else if (Conform (l, r)) {
transform (l.start(), l.end(), r.start(), a.start(), op);
}
else throw invalid_dimensions;

return a;
}

But I am not sure how to declare the third (operation) argument,
presumably a functor, so I can pass it to transform(). The STL
documentation seems to imply that there is a general functor type
called BinaryFunction, but I do not see this in the STL header files,
and I have seen no indications that the functors used have to be
derived from a standard class. On the other hand, I could probably
define the arguent as a template, but then I would end up creating a
large number of copies of the ScalarDyadic() function, one for each
operation. In that case it would probably be more efficient to pass
pointers to binary functions in order to avoid using a template, but I
don't know if transform() would support that.

I would appreciate suggestions.

Thanks.

--- Brian
 
J

John Harrison

Brian McGuinness said:
I have a question about using the STL transform algorithm in a function.
[snip]


But I am not sure how to declare the third (operation) argument,
presumably a functor, so I can pass it to transform(). The STL
documentation seems to imply that there is a general functor type
called BinaryFunction, but I do not see this in the STL header files,
and I have seen no indications that the functors used have to be
derived from a standard class.

It's called std::binary_function and its in the <functional> header file.
But it isn't for deriving from in the way that you are thinking. The purpose
of deriving from std::binary_function is to define certain typedefs such as
result_type.
On the other hand, I could probably
define the arguent as a template, but then I would end up creating a
large number of copies of the ScalarDyadic() function, one for each
operation.

I think that is what you are going to have to do.
In that case it would probably be more efficient to pass
pointers to binary functions in order to avoid using a template, but I
don't know if transform() would support that.

A pointer to a binary function is fine for std::transform, but it is likely
to be less efficient not more. Pointers to functions are potentially less
efficient than functors because they cannot be inlined.

john
 

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

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top