Boost logo

Ublas :

From: Ian McCulloch (ianmcc_at_[hidden])
Date: 2005-07-13 05:12:49

Michael Stevens wrote:

> On Saturday 09 July 2005 03:47, Ian McCulloch wrote:
>> Michael Stevens wrote:
>> > Interesting solution using a 3rd party for traits. If I understand it
>> > correctly it only works for a known and limited set of expressions for
>> > which you can predefine the traits.
>> No, I don't think so: the logic for computing types needs to move into
>> the
>> traits class too. Do you have an example in mind where this could not be
>> done?
> Ian thanks for the reply. I have thought a little more and this should
> make things clearer.
> My case comes from the wish to provide some common functions into the
> uBLAS expression template hierarchy.
> When I use
> struct foo : public expression<foo>
> {
> typedef int size_type;
> };

Should be instead

struct expression_traits<foo>
   typedef int size_type;

> I would be NICE to inherit a bunch of functions whose parameters depend on
> size_type. Because 'foo' is incomplete in the definition of the template
> this cannot be done.

yes. But expression_traits<foo> can be complete, even if foo is not.

> Interestingly it not necessary for a type to be complete to define a
> member function whose signature depends on it. In the case of the
> expression class
> template <class E>
> struct expression {
> typedef E expression_type;
> void expression_function (expression_type);
> void size_function (typename expression_type::size_type);
> The expression_function can be defined but the size_function cannot! Both
> are incomplete.This dichotomy makes me hopeful that there is some trick.
> If E can only be a small number of possible types hen one could use a
> separately specialised trait for each case. This was how I
> (mis)interpreted your solution.

For each derived type, there needs to be a corresponding (partial)
specialization of expression_traits<derived>. They are exactly in 1-1
correspondence; expression_traits defines the types that are needed by both
expression<derived> and derived itself.

> The correct solution is to use an extra template argument thus.
> struct foo : public expression<foo, int>
> template <class E, class S>
> struct expression {
> typedef E expression_type;
> void expression_function (expression_type);
> typedef S size_type;
> void size_function (size_type);

Ouch, that doesn't scale well to additional types! And since size_type is
fixed for each E, it doesn't make much sense to have it as an additional
parameter, it can be computed from E.

> I the case of uBLAS I am reluctant to use this as it has a significant
> effect on the existing syntax. So I am still looking for a trick!

I think the trick already exists: for each existing type derived from
expression<E>, move the typedef's from E itself into expression_traits<E>
(or some other name, if expression_traits is already used for other