473,498 Members | 1,942 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

STL Template question

Hi everyone,

I have a little problem I'm not sure what to do about or if anything can
even be done about it.

Situation is as follows:

I had previous implemented a class called Scalar that is essentially a
wrapper around double that contains an additional field to store what
unit type is represented by this double.

So this allowed me to add 2 values together regardless of their unit
type. For example, 1 inch + 1 millimeter. The way I had implemented this
was just using one class, with a small 2 dimensional table that contained
the conversion factors. Then the various arithmetic operators would do a
lookup in this conversion table using the unit type as index into the
table.

The result works very well, but has a significant performance overhead
compared to just plain double. It pretty much cuts the speed in half.

Also, another problem with this table is that I have the factor "1" going
across the diagonal. So everytime I am performing arithmetic with units
of the same type I have a needless multiply by 1 in there.

This was before I started using STL. =)

Using STL however I came up with a completely different concept that
eliminates the conversion table and the need to store the unit type.

I defined a template class called "Scalar", and then for each unit type,
I also defined an additional class. All classes implement the appropriate
arithmetic operators and the unit type classes contain function that
allow them to convert to other types of units. The Scalar template then
contains conversion operators that will then call the appropriate
conversion function of it's type when necessary.

The benefit of this is that if I add 1 mil to 1 mil, there no longer is a
needless multiply by 1. It is now reduced to 1 double + 1 double and
that's it. Zero performance overhead for adding units of the same type.

If I add units of different type, the conversion operator in the Scalar
template just calls the appropriate conversion function of it's type and
then performs the arithmetic. Advantage here being that the conversion is
now much simpler than before as it now is just a static multiply by a
constant and no longer involves a table lookup. Not as fast as adding
just 2 doubles, but still by magnitudes faster than my previous method.

Also, my memory footprint is significantly reduced as I no longer need to
store a unit type.

So essentially, my code went from this:

Scalar a(1, ScalarUnitMil);
Scalar b(1, ScalarUnitInch);
Scalar c = a + b;

To this:

Scalar<Mila(1);
Scalar<Inchb(1);
Scalar<Milc = a + b;

Now, here is where my problem comes in. Scalar c in my old code is unit
independent. The unit type that it will be depends on the result of a +
b; So if I add inch to an inch then c will be an inch. If I add a
millimeter to a millimeter it'll be a millimeter.

With my STL version however, I have to explicitly state what unit I'm
going to store in it. So no matter what my math operation is, the result
will be Mil.

99% of the time, this isn't a problem. It's a problem 1% of the time when
the user goes to enter data and I then go to store that value. The user
input is going to be converted to whatever unit type I previously defined
in my code and I will loose that information. The value of course will
still be correct, but it'll be in a different unit. This isn't a major
deal-breaker, but if I could avoid it then it would be nice.

So long story short, is there any way to declare variable C in such a way
as to where I don't need to know ahead of time what unit type it's going
to be? I suspect no as I currently can't imagine a way that would be
possible...but since I'm still new to STL I figured I'd ask.

Thanks,

--
Stephan
2003 Yamaha R6

君のこと思い出す日なんてないのは
君のこと忘れたときがないから
Oct 20 '07 #1
4 1555
So long story short, is there any way to declare variable C in such a way
as to where I don't need to know ahead of time what unit type it's going
to be? I suspect no as I currently can't imagine a way that would be
possible...but since I'm still new to STL I figured I'd ask.
No there isn't. Type of a variable must be known at compile time. If I
understand your problem correctly, the best you can do is the following
(assuming that user also entered unit information as a string):

string userUnit = ...
if (userUnit == "Mil")
// Compute and store Scalar<Mil>
else if (userUnit == "Inch")
// Compute and store Scalar<Inch>
else if (...)
// ...etc...

To store the value in a single variable you can use boost::any:

boost::any scalar;
if (userUnit == "Mil")
scalar = Scalar<Mil>(3);
else if (userUnit == "Inch")
scalar = Scalar<Inch>(5);

Note how boost::any gracefully accomodates value of any type. But you still
need the if statements to create scalar of appropriate type. It's also
possible to replace ugly ifs with a more general "factory" for scalars
(untested code):

// Function to create scalar from double
typedef boost::any (*ScalarFactory)(double);

// Template to generate such functions for all unit types you may have
template<class Unitboost::any CreateScalar(double v)
{
return boost::any(Scalar<Unit>(v));
}

// Register all unit types you have in the map
map<string, ScalarFactoryfactoriesByUnit;
factoriesByUnit.insert(make_pair("Mil", &CreateScalar<Mil>));
factoriesByUnit.insert(make_pair("Inch", &CreateScalar<Inch>));
....etc for all supported units

// Now use the factory to create scalar with appropriate unit
double userValue = ...; // Contains value entered by user
string userUnit = ...; // Contains unit entered by user
boost::any scalar = factoriesByUnit[userUnit](userValue);
// Now scalar contains value with appropriate unit.
// Use any_cast to extract the value (but again you must know the unit :-),
// so another map may be necessary)

cheers,
Marcin


Oct 20 '07 #2
Stephan Rose wrote:
....
So long story short, is there any way to declare variable C in such a way
as to where I don't need to know ahead of time what unit type it's going
to be? I suspect no as I currently can't imagine a way that would be
possible...but since I'm still new to STL I figured I'd ask.
I think you need a proxy object.

There is already an open source library that does what you're trying to
do. I can't remember it's name.

Using a proxy object means you don't actually return another Scalar<T>
but an ScalarOperate<T,U,Addand AddScalar has a conversion operator
that works out what you want. The problem of course is that you need to
supply 4 more operators for each binary operator.

If you do find the unit library I'm referring to, do post a link.

This is one library - I'm pretty sure I was thinking of somthing different.
http://enbridge.kundert.2y.net/units/doc/
Oct 20 '07 #3
On Sat, 20 Oct 2007 22:54:31 +0100, Marcin Kalicinski wrote:
>So long story short, is there any way to declare variable C in such a
way as to where I don't need to know ahead of time what unit type it's
going to be? I suspect no as I currently can't imagine a way that would
be possible...but since I'm still new to STL I figured I'd ask.

No there isn't. Type of a variable must be known at compile time. If I
understand your problem correctly, the best you can do is the following
(assuming that user also entered unit information as a string):

string userUnit = ...
if (userUnit == "Mil")
// Compute and store Scalar<Mil>
else if (userUnit == "Inch")
// Compute and store Scalar<Inch>
else if (...)
// ...etc...

To store the value in a single variable you can use boost::any:

boost::any scalar;
if (userUnit == "Mil")
scalar = Scalar<Mil>(3);
else if (userUnit == "Inch")
scalar = Scalar<Inch>(5);

Note how boost::any gracefully accomodates value of any type. But you
still need the if statements to create scalar of appropriate type. It's
also possible to replace ugly ifs with a more general "factory" for
scalars (untested code):

// Function to create scalar from double typedef boost::any
(*ScalarFactory)(double);

// Template to generate such functions for all unit types you may have
template<class Unitboost::any CreateScalar(double v) {
return boost::any(Scalar<Unit>(v));
}

// Register all unit types you have in the map map<string,
ScalarFactoryfactoriesByUnit; factoriesByUnit.insert(make_pair("Mil",
&CreateScalar<Mil>)); factoriesByUnit.insert(make_pair("Inch",
&CreateScalar<Inch>)); ...etc for all supported units

// Now use the factory to create scalar with appropriate unit double
userValue = ...; // Contains value entered by user string userUnit =
...; // Contains unit entered by user boost::any scalar =
factoriesByUnit[userUnit](userValue); // Now scalar contains value with
appropriate unit. // Use any_cast to extract the value (but again you
must know the unit :-), // so another map may be necessary)

cheers,
Marcin
Ahh thank you for the info Marcin.

I'll definitely need to take a closer look at boost then!

Much appreciated,

--
Stephan
2003 Yamaha R6

君のこと思い出す日なんてないのは
君のこと忘れたときがないから
Oct 20 '07 #4
Stephan Rose wrote:
This was before I started using STL. =)
Not directly related to your question, but...

I think you have a misunderstanding about what "STL" means.
"STL" is the old name of the standard C++ library (consisting
of a big bunch of template classes and functions). The acronym
"STL" means "Standard Template Library". Even though it's
technically not the official name of the standard C++ library,
it's still used today informally, for brevity, to refer to the
collection of template classes and functions found in the standard
C++ libraries.

The term you are referring to is simply "template", not "STL".
In other words, eg. "this was before I started using templates".
Oct 24 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
2004
by: Dave | last post by:
Hello all, Consider this function template definition: template<typename T> void foo(T) {} If foo is never called, this template will never be instantiated. Now consider this explicit...
1
2253
by: Alfonso Morra | last post by:
if I have a class template declared as ff: (BTW is this a partial specialization? - I think it is) template <typename T1, myenum_1 e1=OK, my_enum_2=NONE> class A { public: A(); virtual...
10
2071
by: Suki | last post by:
Hi, I'm writing a templated class, and i dont want to use the class otherthan for some predetermined types, say, int, double etc. This class has no meaning for typenames other than those few. ...
12
2591
by: mlimber | last post by:
This is a repost (with slight modifications) from comp.lang.c++.moderated in an effort to get some response. I am using Loki's Factory as presented in _Modern C++ Design_ for message passing in...
1
2537
by: Leslaw Bieniasz | last post by:
Hello, I have the following problem: file a.h --------------- template <class T> class A { // some stuff
2
2293
by: pookiebearbottom | last post by:
Just trying to learn some things about templates. Was wondering how boost::tupple really works, but the headers were a bit confusing to me. I know you get do something like the following, just...
45
2839
by: charles.lobo | last post by:
Hi, I have recently begun using templates in C++ and have found it to be quite useful. However, hearing stories of code bloat and assorted problems I decided to write a couple of small programs...
2
2563
by: aitrob | last post by:
Hi, I have a problem concerning templates/inheritance. I have a code that compiles fine with g++ 4.0.1 (Apple version), but gives a lot of errors with Intel C++ 10.1 (Mac OS X). I'm not sure if...
4
3000
by: David Sanders | last post by:
Hi, I have a class with an integer template parameter, taking values 1, 2 or 3, and a function 'calc' in that class which performs calculations. Some calculations need only be performed if the...
3
1836
by: stdlib99 | last post by:
Hi, I have a simple question regarding templates and meta programming. I am going to try and work my way through the C++ Template Metaprogramming, a book by David Abrahams and Aleksey...
0
7125
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7002
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7165
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
6885
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7379
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
4588
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3093
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3081
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1417
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.