Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2004-01-06 01:05:48


"Dan W." <danw_at_[hidden]> wrote in message
news:btcqro$peq$1_at_sea.gmane.org...
> Andy Little wrote:
> > "Dan W." <danw_at_[hidden]> wrote in message

> I'd say, ints is fine, but you need numerator and denominator, I
> suppose. But if someone tomorrow needs a non-fractional power you're
> toast. How about making the type of the power a template parameter? Is
> that doable?

( BTW re your prev example... You Cant use floats as template params... not
allowed in C++:
                       template< float T> // ERROR invalid template params
                        class my_class; ... Why... basically (I think)
because compile time float calcs are too tricky across compilers)
...Yep... my use of ints as template params is short sighted e.g:
  extract the abstract_pq from the above.
(and for brevity use three dimension params, in sequence
dimension-of-Length, dimension-of-Time, dimension-of-Mass)
then it could be declared as:
template< int L, int T, int M>
class abstract_pq{...};
To represent an abstract force (aside for the potential founders of the
brave new world of physics: using SI)
it has dimensions of length to power 1, mass to power 1,
using ints (as above)
abstract_pq< 1,1,-2> Force;
notably though because ints are 'non-type template parameters' I can only
ever use
ints.
So as you say I can never represent real powers here... ie its short
sighted.
however if I named some ints
 static int const one = 1;
  static int const minus_two = -2;
I could still represent Force using the names at source code level:
abstract_pq< one,one,minus_two> Force;
But because they are names they are more versatile:
A simple metaprogramming class
template< int x>
struct Rep{
    const static int value = x; // notably 'static' Therefore I do not
need a class object to get at this name
};
Now I could do major mods to the implementation:
Using Rep I can redo my names as types:
typedef one Rep<1>;
typedef two Rep<2>;
typedef minus_one Rep<-2>;
the value is available but with a bit more work:
int x = one::value; // ie x =1;
Changing the declaration/def of abstract_pq
template< typename L, typename T, typename M>
class abstract_pq{
private: // nobodys business what goes on in here
        static int const from_p1 = L::value; // extract the value from
the type... any Type with a suitable 'value' will work
    ...
};
and now :
abstract_pq< 1,1,-2> Force1; // ERROR invalid template
arguments
abstract_pq< one,one,minus_two> Force; // ok still works fine using the new
definitions
ie names are much more versatile... the Rep types could be replaced by
Rationals etc
But some downsides are: it puts a lot of people off (why say 'one', not 1 )
...its another layer of complexity... its harder to debug.
Nevertheless I shall probably have to go that way.

> And the value type has to absolutely be a template type. Someone will
> want a 7-bit type to make prinatble ascii characters a dimension... you
> never know.

Oops ....... The value_type is and has always been part of it:
> > p_quantity<abstract_pq<1,0,0,0,0,0,0>,int,0,0> length;
 (or whatever value_type) ^^^ missed out in
the above
Also... BTW.. converts... between value_types:
p_quantity<...,int,...> x;
p_quantity<...,float,...> y;
        y = x; // ok... (aside... Yes aware of the concerns)
 and promotes
     x * y ---> p_quantity<...,float,...>
IOW its designed to work like inbuilt types as far as possible.

> Template type for now. Don't even bother with such details.

(I Accept that abstract_pq template params may need to be types as above.)
However I need something that works for me Now, Now, Now
My major Major criticism of all the other units libs is "Heres My Great
Lib..."
then there are a couple of headers of template code
followed by 'Oh ...BTW... you have to define your own units... dont worry
it'll be no problem' .
My reaction as a user is ... What the ( expletive deleted) is this (
expletive deleted) ?

> A float type loses accuracy on accumulation, has 3 or four states that
> mean zero depending on perspective... If you're prepared to deal with
> all that in representing fractionals with it, fine. I would just
> procrastinate the descision, or even defer it to the user.

Yep floats are ideal in theory ... ghastly in practise.
Next version will probably move to type params but basically will probably
be wrapping an int(again) as shown in the rep example.
ie my advice on non-integer powers will still probably be go back to
inbuilts.
Even with integer only powers the thing is useful. I dont need fractional
powers much... when I do I'll follow my advice... But will watch to see what
others come up with.

BTW >>Current noise: nA/(Hz^(0.5)) //"nano-Amps per root-Hertz"
>>Voltage noise:
Is very useful.
Can use this for a 'how to work around limitations of my type' example ...
Thanks :-)

> I know, I wish I could give you a hand, but I'm not at 1% the caliber of
> yourself or most programmers around here. I've yet to come to grips with
> "traits", never mind meta-programming... But you've done all this 7
> times already! :)

Yep and BIG WARNING the next version will be "All change" again.
Nevertheless the user level stuff has remained Reasonably consistent.

> 5 years ago or so I downloaded SI units library, and worked on trying to
> understand it for maybe a week straigh, and finally gave up.

Yep ... Dont have a clue what this SIUnits syntax is about:
Length L = 5 * meters ;
I tend to assume that operator * means multiply... Nope apparently not in
SIUnits.
I got as far as the docs and just said NO (expletive deleted) WAY!
OTOH you and many other seem happy with it... sorry makes no sense to me
my equiv looks like this... underneath it is a p_quantity<...> as above but
the declaration style is a convenience intended for legibility.
(the pq_ prefix is designed to reduce name collisions)
pq_length<double>::m L(5); // L is a length in meters..'m' is the SI
naming convention for meters... all SI types use the standard SI name for
the unit:
pq_force<int>::kN f(1); //a force in newtons 'kN' is SI convention for
units of kilo-newtons, initialisation style is common practise;
alternatively for less keyboard wear on most common value_type:
q_length::m L1( 5) ; // internal double value_type
q_force::kgf f1(1); // kgf is a non-SI unit... the type can represent
physical_quantities using SI and non-SI units
its a standard type and can be thrown about like any other:
std::vector<q_pressure::MPa> vect(1000); // pressure in mega-pascals

[snip]

> No idea what PDG means.

Pretty Darned Good

>
> > Try out my examples as they are ... (gcc 3.2, VC7.1 ... I hope will work
on
> > close conforming compilers.... feedback on compile run would be very
> > helpful).
> > http://www.servocomm.freeserve.co.uk/Cpp/pqs-1-00-01/download.html
>
> I'm also using the Digital Mars compiler, for which there's no boost
> support yet.

The download has No Dependencies except the STL.
 It uses, acknowledges and hopefully respects copyright of boost stuff but
doesnt require the boost libs in any way. That said it does require a close
standard conforming compiler VC7.1 ...
Thanks microsoft, gcc 32.2.. Thanks GNU
For others I dont know if it works or not... if its old ... probably not

> Haven't tried your library, but I found the syntax a
> bit daunting,

hmm ... ok.. I will have to think about that...

> not that I found Matthias' any less daunting. But I
> didn't really spend even an hour on either. I just figured, if it's not
> plainly obvious how to do it, few people will use it anyways;

Yep... agree absolutely.

> and like I
> said, what I *needed* it for, in my present project, was to count bytes
> with a short, and things like that; which I would rather use a typed
> type, but one that doesn't impose on me that I use double, etc.

Hmm... sounds like you will have to wait for someones "all singing "
version... maybe Mathiass Schabel is your man.
my lib is called *physical*_quantities... it does what its says on the tin.

regards
Andy Little


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