Boost logo

Boost :

From: Brook Milligan (brook_at_[hidden])
Date: 2008-07-25 13:36:54


Brian Davis writes:
> The goal I have/desire is to preform type transformations and allow the
> programmer to specify these transformations in a generic way

That is more or less the same goal as I have for the Domain library.
>From what you say below, though, it seems that there may be some
differences in design or focus. You seem to focus on what happens
during an assignment, and want a single assignment to be reflected in
the value of potentially a number of other variables.

In contrast, I am thinking of what happens when other functions
(including but not limited to operators) are called. The idea was to
allow the user of the Domain library (I envision this person most
likely being a developer of another domain-specific library) to craft
the set of type tags, conversion functions, and functions/operators,
and then have an idiomatic MPL-based means of specifying how they all
go together. The job of the Domain library would be to invoke the MPL
code for domain selection, etc. so that the user of the library would
not have to worry about this and even more so, so that the user of
that library would never have to worry about domain transformations
when they call the functions/operators but could rely on domain
correctness, even in completely generic algorithms.

I will give more thought to rolling the assignment operator into this,
but I'm not sure yet how the two ideas fit together.

> For type T1 and T2 allow the programmer to specify f(T1 t1, T2 t2 ) and g(T1
> t1, T2 t2 ) where f and g are transformation functions from T1 -> T2 and
> T2->T1 respectively.

Yes, I have in mind exactly these sorts of functions being made by the
user of the Domain library.

> Overloading operator= and specifying f(T1 t1, T2 t2 ) := t2 = t* 1/2 and
> g(T1 t1, T2 t2 ):= t1 = t2*2 allowing the programmer to type

> Transformations shall allow chaining/cascaded to be specified.

> Transformations shall support bidirectional and unidirectional updates.

As mentioned above, this is what I have not really been thinking about.

> Where if there exists no clear transformation... the programmer shall be
> allowed to specify one.

Of course.

> Yes so some types can not be automatically transformed. My example provides
> absolutely no support for this except for 1 to 1 translation... for
> disparate types it is... well... compiler errors waiting to happen if no
> translation functions are supplied.

You mention the possibility of a 1:1 transformation. In my context,
I'm not certain what that means. To me that signifies two different
types in the same domain. Those can only be differentiated with
respect to their value types (i.e., the types actually holding the
data as opposed to the parts that track the domain information). In
my scheme, as long as one value type can be constructed from another,
there is always such a transformation within the same domain. No need
for special support. Did you have something else in mind?

It will always be the case that certain operations make no sense for
certain domains. Thus, it is possible to try to use expressions on
the generic domain types that cannot be resolved by the appropriate
template specializations. I see this as no different from trying to
use any ill-defined expression, though. The compiler will catch it,
you will pay more attention to the documentation that describes what
is legal for that domain, and you will fix your code. What else is
possible?

> The software engineer shall be allowed to specify a transform is the
> compiler cannot automatically figure it out.

More precisely, the engineer must specify a transformation between
domains that must be interconverted. Except for the trivial case of
transforming between value types within a domain, which is really not
a domain transformation at all, the compiler cannot possibly know what
transformation is appropriate.

The goal here is to make it easier for an engineer to construct a
library appropriate to a particular set of domains (an application
domain if you will) so that the users of his/her library in turn have
a truly easy set of generic, but domain-aware, operations to work
with.

> How difficult is it to specify new types and tranforms.... Are we talking
> about the types like thoes defined by the section titled "A Deeper Look at
> Meatafunctions - 3.1 Dimensional Analysis" in "C++ Template Metaprogramming"
> by David and Aleksey? If so ... ouch... could be quite painful to specify
> new types and conversions... What is your approach?

Developing a domain-aware library based upon the Domain library
essentially involves the following:

- Naming the set of domains and the individual domains within the set.
  This is only a matter of creating a set of tags for dispatching;
  essentially this is an organized set of empty structures to create
  convenient names that guide template specialization.

- Potentially, creating an appropriate set of value types to hold
  whatever information is needed. In many cases, these will be
  preexisting types; in others, they will need special construction.
  As always, it all depends on the application domain.

- Creating the domain transformation functions. These are a set of
  specializations of template functions within a defined namespace.

- Potentially creating any appropriate definitions for operators.
  These are a set of specializations of classes within a defined
  namespace.

- Potentially creating non-operator functions on the domain types.
  Since these cannot be known in advance (unlike the operators), a bit
  more work is required on the part of the user of the Domain
  library. However, this is largely idiomatic and easily supported
  within the framework.

- Identifying which domain transformations are available. This
  involves a specialization of a single class within a defined
  namespace.

- Identifying which domains are appropriate for which operations. For
  example, additive operations may be defined for all domains, but
  multiplicative ones defined only for some. This is handled by a set
  of simple MPL vectors of domains. The library takes care of sorting
  through the domains of function arguments, the set of domain
  interconversions, and the domains that are appropriate for the
  called operation to find an appropriate domain. The arguments are
  converted to the target domain if necessary before the operation is
  performed. This is perhaps the main thing that makes the library
  useful, as this makes the operations generic while maintaining
  domain-correctness.

> Yes sounds great with the exception of the "operators portion"... like every
> one in boost using operators for new purposes (think Spirit - and I don't
> mean this in a bad way) we are running out of operators which provide
> meaningful schematics...

I am thinking of cases in which the operators already have a natural
meaning in the application domain being modeled by all the domain
types, but that the implementations might differ among domain types
and so interconversions are required. This is quite different than
overloading operators to describe an entirely new language, as Spirit
does.

> What happens when and operation cannot be found in a domain, but the
> programmer can or needs to specify one? Is it extensible?

Yes, generally by specializing things in well-known namespaces.

> The easier it is to provide new specifications for types and their
> transformations the better.... you'll never think of every domain and
> translation. Need to supply a clear path to adding new types, domains, and
> translations.

Of course. The goal is to make it easy and idiomatic for others to do
this, not to anticipate all possible uses. As I mentioned, the role
of this is as a base layer upon which application domain-specific
libraries are easy to build.

> How do I obtain the code and where is the problem?

I'll try to get it in shape for public consumption this weekend. I
have a worked example based on a toy polynomial library to illustrate
how to build a library on top of the Domain library. However, the
documentation is mainly in the form of Doxygen comments and so I need
to give a bit more of the overview. Stay tuned. ...

> Gerneric domain is exactly what I am after. We have type T1, T2, T3,....TN
> and we have to translate between them... What's the easiest way to specify
> this for the programmer?

That and how to automate the process of choosing the transformations
is what I'm trying to make easy. As soon as I can get the code out
there, please let me know how to improve the ideas.

Thanks alot for your interest so far. I look forward to additional
comments.

Cheers,
Brook


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk