Boost logo

Glas :

[glas] proposals

From: Karl Meerbergen (Karl.Meerbergen_at_[hidden])
Date: 2007-02-05 05:02:45

Dear List,

I am hesitating between two conceptual systems for glas.
None of them is ideal, but we have to make a choice and perhaps someone
comes up with a better idea.

The idea is to use Concept C++, but also provide a working system for a
C++ compiler.

I have the following concepts (among others)

ScalarExpression: e.g. double
VectorExpression: e.g. result_type of add(vector,vector)
DenseVectorExpression: e.g. dense_vector<double>

ScalarCollection: e.g. double
DenseVectorCollection: e.g. dense_vector<double>

The Expression and Collection concepts are set up in a tree fashion. For
each Expression, there is a corresponding Collection (one-one

The root is Expression/Collection with two children:
* ScalarExpression/ScalarCollection
* VectorExpression/VectorCollection

VectorExpression/vectorCollection has one child:
* DenseVectorExpression/DenseVectorCollection

The difference between expression and collection lies in that an
expression is not mutable.

OK. So far the basics. Using Concept C++, these can be used to dispatch
an expression like

assign( v, add( x, y ) )

to the most suitable implementation, following the tree structure of
expression and collection. I do not give the details here.

For the C++ compiler, this is more tricky:
I see two possibilities:

A) Use meta programming to examine an expression.
For each type, we can ask questions about where we are in the concept
tree. In the above example,

concept_tag< dense_vector<double> >::type == dense_vector_collection_tag

concept_tag< double >::type == scalar_collection_tag

For the dispatching, it might be useful to know which type of expression
we are working with, e.g.

which_kind< vector_expression_tag, dense_vector<double> >::type ==

which_kind< collection_tag, dense_vector_<double> >::type ==

The which_kind meta function selects the concept that is a child in the
concept tree.

B) Use Bartan-Nackman trick

For each concept, we provide a type, e.g.

template <typename E>
struct dense_vector_expression
: vector_expression<E>
} ;

All GLAS types inherit from a concept type that can be used in
dispatching, e.g.

template <typename T>
class dense_vector
: public dense_vector_collection< vector<T> >
, public dense_vector_expression< vector<T> >
} ;

This system is very close to the concept c++ concept system and
therefore I like it very much, but the disadvantage is that built-in
types do not have this mechanism: e.g.

class double
: public scalar_expression<double>
, public scalar_collection<double>
} ;

So, we should define glas::double, glas::complex, glas::int etc.

System B is relatively easy to put together. With system A, the GLAS
user can use his own classes in GLAS whithout having to use the Barton
and Nackman trick for his own classes, and built-in types perfectly fit
into the system. If we choose A, we should use this also with Concept
C++, otherwise we have two completely different systems, which is overkill.

I hope my explanation is clear. It is rather technical matter.

Thanks for your reactions.