Re: Second draft (was Re: Framework for iterating over product types?)
Ben Rudiak-Gould wrote:
[..]
There are many classes for which swap() can be defined like this:
swap(this->a, other.a);
swap(this->b, other.b);
swap(this->c, other.c);
// ...
and serialize() can be defined like this:
ar & a;
ar & b;
ar & c;
// ...
and operator==() can be defined like this:
if (!(this->a == other.a)) return false;
if (!(this->b == other.b)) return false;
if (!(this->c == other.c)) return false;
// ...
and operator<() can be defined like this:
if (this->a < other.a) return true;
if (other.a < this->a) return false;
if (this->b < other.b) return true;
if (other.b < this->b) return false;
if (this->c < other.c) return true;
if (other.c < this->c) return false;
// ...
and so on. It's a hassle to write this boilerplate for a large number
of user-defined classes. All of the above boilerplate functions can be
auto-generated from a single per-class boilerplate method looking
something like this:
template<class Visitor>
static void enum_children(Visitor& has) {
has (&Foo::a) (&Foo::b) (&Foo::c) /* ... */ ;
}
for example, here's how to do it for swap():
template<class T>
class swap_member {
public:
swap_member(T& a, T& b) : a(a), b(b) {}
template<class X>
void operator()(X T::* p) {
swap(a.*p, b.*p);
}
private:
T& a; T& b;
};
template<class T>
void generic_swap(T& a, T& b) {
T::enum_children(swap_member(a,b));
}
For a system with a lot of boilerplate methods of this kind, this
technique looks like it could save a lot of time and avoid a lot of
bugs. I was surprised not to find support for it in Boost. I can
write my own implementation, but I'd rather use someone else's, or at
least use a standardized name for the method (instead of
"enum_children") for future compatibility. So, has anyone implemented
this before or chosen a naming convention for it?
In all of my programming career the need for a struct/class like that
have not arisen even once. Forgive my bluntness, but it looks like
an exemplary representation of a pure numerical (and rather table-
oriented) data chunk. For such data it is advised NOT to write
operator<, operator==, etc., as member functions. Use stand-alone
functions instead.
I honestly doubt that you have "a large number of user-defined classes"
that all look like the one you presented here. Two, three, maybe, but
"a large number"?
As to whether it's been done before, I am not sure, but if it hasn't,
write it (since you claim you can) and submit it to Boost. That's
how Boost grows. You will undoubtedly find those who also need the
functionality; they might even be interested in helping you write it,
and if not, no big deal, they'll tell you what's wrong with yours.
If you don't find people who need something like that, well, you may
be alone, but they you're stuck implementing it for yourself anyway.
And to simplify the task I'd probably put those 'a', 'b', 'c', etc.
members in arrays of the respective types (hopefully they are all
pretty much the same, aren't they?), and to access them I'd have the
member functions that would simply returned the array elements (by
ref or by value)...
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask