# Physics data classes?

This topic is 4676 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I was thinking if the following would be a good or bad idea: Let's say we have a physics engine, and lets say this engine uses physical dimentions such as distance, time and velocity. What if for each dimention you would create a class. So if you have:
time a;
distance b;

a = b; // <= compilation error

The assigment operation will produce a compilation error. However, you could define in the class operations between different dimentions. For example:
time a;
distance b;
velocity c;

b = a*c; // <= Ok!

So a*c will return a value of class distance. Another bonus, is that you wont be able to use functions such as sin on a dimention class, unless you explictly cast the variable. What will be the speed cost for this? However, will it improove the developement productivity and prevent bugs? What do you think? Thanks in advance.

##### Share on other sites
Generally speaking, operator overloading (like what you suggest) is one of C++'s most useful features. I absolutely think that what you suggest is a good idea.

##### Share on other sites
You can try to overload operators to handle such operations.

##### Share on other sites
I decided to have some fun with this problem. Here is a template-based solution based on the fact that units behave exactly like vectors:

#include<iostream>#include<sstream>// Argument order: KG M S                                                                                                                                                                                                                       template<int KG, int M, int S>class TUnit {public:  static std::string Describe( ) {    std::stringstream str;    if( KG != 0 ) {      str << " kg";      if( KG != 1 ) {        str << "^" << KG;      }    }    if( M != 0 ) {      str << " m";      if( M != 1 ) {        str << "^" << M;      }    }    if( S != 0 ) {      str << " s";      if( S != 1 ) {        str << "^" << S;      }    }    return str.str( );  }};template<int KG, int M, int S>class TValue {  float value;public:  typedef TUnit<KG,M,S> Unit;  typedef TValue<KG,M,S> Self;  TValue( float value ) : value(value) { }  float Value( ) const { return value; }  // Same-unit operations                                                                                                                                                                                                                         Self operator+( const Self & other ) const { return Self( value + other.value ); }  Self operator-( const Self & other ) const { return Self( value - other.value ); }  Self & operator+=( const Self & other ) {    value += other.value;    return *this;  }  Self & operator-=( const Self & other ) {    value -= other.value;    return *this;  }  // Different-unit operations                                                                                                                                                                                                                    template<int KG2, int M2, int S2>  TValue<KG+KG2,M+M2,S+S2> operator*( const TValue<KG2,M2,S2> & other ) const {    return TValue<KG+KG2,M+M2,S+S2>( value * other.Value( ) );  }  template<int KG2, int M2, int S2>  TValue<KG-KG2,M-M2,S-S2> operator/( const TValue<KG2,M2,S2> & other ) const {    return TValue<KG-KG2,M-M2,S-S2>( value / other.Value( ) );  }  Self & operator*=( const TValue<0,0,0> & other ) {    value *= other.Value( );    return *this;  }  Self & operator/=( const TValue<0,0,0> & other ) {    value /= other.Value( );    return *this;  }};template<int KG,int M,int S>std::ostream & operator<<( std::ostream & os, const TValue<KG,M,S> & val ) {  typedef typename TValue<KG,M,S>::Unit SelfUnit;  os << val.Value( ) << SelfUnit::Describe( );  return os;}typedef TValue<0,0,0> Scalar;typedef TValue<0,1,0> Distance;typedef TValue<0,0,1> Time;typedef TValue<0,1,-1> Speed;typedef TValue<0,1,-2> Acceleration;typedef TValue<1,0,0> Weight;typedef TValue<1,1,-2> Force;int main( ) {  Distance d( 10000.0f );  Time t( 3600.0f );  Speed s = d / t;  std::cout << d << std::endl;  std::cout << t << std::endl;  std::cout << s << std::endl;  std::cout << t * d / Force( 10.0 ) << std::endl;  std::cout << sizeof(d) << std::endl;}

You can't compile things like s+t.

Improvement to add: make an implicit float -> TValue<0,0,0> constructor, and make the other constructors explicit. And maybe make a better formatting for unit display, and for unit creation syntax.

EDIT: made the operator<< rhs argument a const reference, to display the result of a computation directly.

##### Share on other sites
I'm sure I've seen a SI units c++ library somewhere...

EDIT: Here is one implementation: http://enbridge.kundert.2y.net/units/doc/

##### Share on other sites
However, since a physics engine might require a lot of calculations, how will it affect the performance?

##### Share on other sites
Quote:
 * Low speed overhead. All units management is enforced by the C++ compiler. Mathematical equations using units should be just as fast as those without. In fact, this can be tested, by turning off the units management using a compile-time definition.

##### Share on other sites
Quote:
 What will be the speed cost for this?

As dalleboy's quote said the cost can be nothing, you just have to write things correctly so that the compiler will do all the unit checking at compile time and inline all the operations. This shouldn't be that hard to do (I'm pretty sure ToohrVyk's solution will have no overhead when you turn on compiler optimizations).

1. 1
Rutin
26
2. 2
3. 3
4. 4
5. 5

• 10
• 13
• 19
• 14
• 9
• ### Forum Statistics

• Total Topics
632941
• Total Posts
3009333
• ### Who's Online (See full list)

There are no registered users currently online

×