July 19, 2005
BCS wrote:
> In article <dbeh1t$12p4$1@digitaldaemon.com>, AJG says...
> ..
> 
> 
>>Yeah, I'm finding out more and more exotic uses for templates... this would all
>>get much better if implicit instantiation were possible. 
> 
> 
> ..
> 
> 
>>--AJG.
>>
>>
> 
> 
> While we are whishing, how about implicit instantiation defining the return type
> of a function as a function of the inputs. That would allow something like this:
> 
> #// a Unit (m, km, kg, lb, etc.) safe arithmetic type
> #
> #template Unit(T, int d, int m, int t)
> #{
> #   typedef T Unit;
> #   #   Unit!(T,d,m,t).Unit opAdd(Unit!(T,d,m,t).Unit v1, Unit!(T,d,m,t).Unit v2)
> #   {
> #      return csat(T)v1 + cast(T)v2;	
> #   }
> #   Unit!(T,d,m,t).Unit opSub(Unit!(T,d,m,t).Unit v1, Unit!(T,d,m,t).Unit v2)
> #   {
> #      return cast(T)v1 - cast(T)v2;	
> #   }
> #   #   Unit!(T,d1+d2,m1+m2,t1+t2).Unit opMul(Unit!(T,d1,m1,t1).Unit v1,
> Unit!(T,d2,m2,t2).Unit v2)
> #   {
> #      return cast(T)v1 * cast(T)v2;	
> #   }
> #
> #   Unit!(T,d1-d2,m1-m2,t1-t2).Unit opMul(Unit!(T,d1,m1,t1).Unit v1,
> Unit!(T,d2,m2,t2).Unit v2)
> #   {
> #      return cast(T)v1 / cast(T)v2;	
> #   }
> #}
> 
> I know, I know, implementing this would likely be a royal mess. One possible
> means to simplify it would be to require a list of allowed instantiations e.g.
> 
> # instance Unit !(real, 1, 0, 0) ; // meters
> # instance Unit !(real, 0, 1, 0) ; // kg
> # instance Unit !(real, 0, 0, 1) ; // seconds
> # instance Unit !(real, 1, 0, -1) ; // m/s
> # // etc…
> 
> 
> BCS
> 
> p.s
> One quirk of the above example is that it can optimize to the same code you
> would get with using just reals.
> 
> 

Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve?

I do something like this in my programs already, and its more readable.

struct Length // stored in meters
{
  float units = 0;
  float meters() { return units; }
  float meters( float f ) { return units = f; }

  float feet() { return meters * FeetPerMeter; }
  float feet( float v ) { return units = ( v / FeetPerMeter ); }
  ...
  Length opAdd( Length L ) {
	Length tmp;
	tmp.units = this.units + L.units;
	return tmp;
  }
}

Length a,b,c;
a.feet = 20;
b.meters = 15;
c = a + b;

-DavidM


July 19, 2005
>
>Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve?
>
>I do something like this in my programs already, and its more readable.
>
>struct Length // stored in meters
>{
>   float units = 0;
>   float meters() { return units; }
>   float meters( float f ) { return units = f; }
>
>   float feet() { return meters * FeetPerMeter; }
>   float feet( float v ) { return units = ( v / FeetPerMeter ); }
>   ...
>   Length opAdd( Length L ) {
>	Length tmp;
>	tmp.units = this.units + L.units;
>	return tmp;
>   }
>}
>
>Length a,b,c;
>a.feet = 20;
>b.meters = 15;
>c = a + b;
>
>-DavidM
>
>


Yes, that would be more convenient if I was only dealing with distances. However it would allow something like the following to compile:

Distance a, b, c;

a.meters = 15;
b.Newtons = 5
c = a + b;

Meters plus Newtons is not only meaningless, it is invalid. The template construct that I suggested, would ensure that only Unit of similar types can be added. It would also ensure that all other math operations result in the right type of unit.

One solution that I have considered acutely implementing is vary similar to what I suggested, but done as a class with all of the checks done at runtime and the dimensions carried along with the value in an object. It would have significant runtime overhead where as the template method would run as fast as using just bare reals.


July 19, 2005
BCS wrote:
>>Would it not be easier just to store the value as one quantity, say meters and use member functions to store/retrieve?
>>
>>I do something like this in my programs already, and its more readable.
>>
>>struct Length // stored in meters
>>{
>>  float units = 0;
>>  float meters() { return units; }
>>  float meters( float f ) { return units = f; }
>>
>>  float feet() { return meters * FeetPerMeter; }
>>  float feet( float v ) { return units = ( v / FeetPerMeter ); }
>>  ...
>>  Length opAdd( Length L ) {
>>	Length tmp;
>>	tmp.units = this.units + L.units;
>>	return tmp;
>>  }
>>}
>>
>>Length a,b,c;
>>a.feet = 20;
>>b.meters = 15;
>>c = a + b;
>>
>>-DavidM
>>
>>
> 
> 
> 
> Yes, that would be more convenient if I was only dealing with distances. However
> it would allow something like the following to compile:
> 
> Distance a, b, c;
> 
> a.meters = 15;
> b.Newtons = 5
> c = a + b;
> 
> Meters plus Newtons is not only meaningless, it is invalid. The template
> construct that I suggested, would ensure that only Unit of similar types can be
> added. It would also ensure that all other math operations result in the right
> type of unit. 
> 

Why not make a Force struct for Newtons?  Then they cannot be added together.  The type system already supports this type of checking.

As a matter of fact you could do things like:

Velocity v;
Time t;
Distance d;

d.meters = 100;
t.seconds = 10;
v = m / t;

> One solution that I have considered acutely implementing is vary similar to what
> I suggested, but done as a class with all of the checks done at runtime and the
> dimensions carried along with the value in an object. It would have significant
> runtime overhead where as the template method would run as fast as using just
> bare reals.
> 

I dont see your solution being any faster, except for possible constants(compile time).  My above code will optimize down to just reals.

-DavidM
July 19, 2005
In article <dbjeca$ejm$1@digitaldaemon.com>, BCS says...
>
>Yes, that would be more convenient if I was only dealing with distances.
..

I just looked again at what you proposed and noticed that it explicitly deals with length. My bad, (:P) that makes about half of my last post junk.

On the other hand, that solution requires a different struct to be declared for
each type of unit that is going to be used. This vary quickly gets impractical,
one quick google search found a list of about twenty categories of BASIC units,
not even getting into things like the units of the various constants. Addition
is bad enough, but multiplication quickly turns into a nightmare.
For things that don’t use to many units, using structs would be just fine,
however I tend to end up using more complicated units and would like something a
bit more flexible




July 19, 2005
In article <dbjigh$hva$1@digitaldaemon.com>, David Medlock says...
>
>Why not make a Force struct for Newtons?  Then they cannot be added together.  The type system already supports this type of checking.
>

see my last post (they crossed in cyber space)


>> One solution that I have considered acutely implementing is vary similar to what I suggested, but done as a class with all of the checks done at runtime and the dimensions carried along with the value in an object. It would have significant runtime overhead where as the template method would run as fast as using just bare reals.
>> 

>I dont see your solution being any faster, except for possible constants(compile time).  My above code will optimize down to just reals.
>
>-DavidM


The class solution would be slower (but would allow runtime units). As to the template solution, its advantage over the structs is not speed (I agree they would run at the same speed) but implementation. It is one typedef where the structs would require anywhere from about 5 or 6 to upwards of 50 different types of structs depending on what you are doing.

On the other hand it requires a lot more from the compiler.


1 2
Next ›   Last »