By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,109 Members | 932 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,109 IT Pros & Developers. It's quick & easy.

Expect ArithmeticType to have limits?

P: n/a

Let's say we want to write a function which calculates the force which
earth's gravity exerts on an object of particular mass at sea level. We
could start off with:

unsigned CalcForce(unsigned const mass)
{
return mass * 9.81; /* Let's ignore the rounding-down */
}

Of course though, C++ has many built-in arithmetic types; we could as
easily have written it as:

double CalcForce(double const mass)
{
return mass * 9.81;
}

or:

long unsigned CalcForce(long unsigned const mass)
{
return mass * 9.81;
}

So this might lead us to write a template function which can deal with any
arithmetic type. We might start off with:

template<class T>
T CalcForce(T const mass)
{
return mass * 9.81;
}

The problem with this, however, is that it is TOO generic -- it could be
passed anything from a pointer to an std::string! In an attempt to restrict
the possibilities, maybe we could try:

#define COMPASS /* Compile-time assertion */

#include <limits>

template<class T>
T CalcForce(T const mass)
{
COMPASS(std::numeric_limits<T>::is_specialized);

return mass * 9.81;
}

Do you think this is a wise way to write a generic function which deals
with numbers?

Lastly, let's say that we want this function to work with user-defined
arithmetic types also, such as a BigNum library. Should any such classes be
expected to have a specialisation of "numeric_limits"?

--

Frederick Gotham
Sep 23 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Frederick Gotham wrote:
So this might lead us to write a template function which can deal with any
arithmetic type. We might start off with:

template<class T>
T CalcForce(T const mass)
{
return mass * 9.81;
}

The problem with this, however, is that it is TOO generic -- it could be
passed anything from a pointer to an std::string! In an attempt to
restrict the possibilities, maybe we could try:
You can't pass anything. If you specialize it for anything that has not an
adequate operator * it will not compile. The problem is that the error
message can be difficult to understand, but there are ways to work around
that. There is paper about this in Stroustrup's web, for example.
template<class T>
T CalcForce(T const mass)
{
COMPASS(std::numeric_limits<T>::is_specialized);

return mass * 9.81;
}

Do you think this is a wise way to write a generic function which deals
with numbers?

Lastly, let's say that we want this function to work with user-defined
arithmetic types also, such as a BigNum library. Should any such classes
be expected to have a specialisation of "numeric_limits"?
If you write code like this you are effectively expecting it. I see one
problem with this approach. One programmer may want to use your function
with a third part BigNum class that does not have that specialization. No
problem, they say, I can write it on my own. Later, a new version of the
BigNum class is released, and now it has the specialization of
numeric_limits. The program must be adapted, or must use conditional code
to be able to compile with any BigNum version.

IMO is more practical to check only for what you need: the availability of
an adequate operator *, in this case.

--
Salu2
Sep 23 '06 #2

P: n/a
Frederick Gotham wrote:
>
The problem with this, however, is that it is TOO generic -- it could be
passed anything from a pointer to an std::string! In an attempt to restrict
the possibilities, maybe we could try:

#define COMPASS /* Compile-time assertion */

#include <limits>

template<class T>
T CalcForce(T const mass)
{
COMPASS(std::numeric_limits<T>::is_specialized);

return mass * 9.81;
}
Decide which numeric types you're using in your program and write
functions that take those types. Supporting two or three types doesn't
require templates. Further, getting good results from numeric
computations means writing type-specific code -- it varies depending on
the details of the type. You can't, in general, write it generically.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Sep 23 '06 #3

P: n/a
Pete Becker posted:
Decide which numeric types you're using in your program and write
functions that take those types.

The point is to write portable code which can be used for all sorts of
different integer types, including the linkes of:

__int256 a,b = 34,c;

a = CalcForce(b);

Supporting two or three types doesn't require templates.

The point is to support *all* arithmetic types, including user-defined
ones.

Further, getting good results from numeric computations means writing
type-specific code -- it varies depending on the details of the type.
You can't, in general, write it generically.

I write arithmetic generic code all the time -- all you need is a robust
understanding of integer promotion and conversion.

--

Frederick Gotham
Sep 23 '06 #4

P: n/a
Frederick Gotham wrote:
Pete Becker posted:
>Decide which numeric types you're using in your program and write
functions that take those types.


The point is to write portable code which can be used for all sorts of
different integer types, including the linkes of:

__int256 a,b = 34,c;

a = CalcForce(b);
Why?
>
>Supporting two or three types doesn't require templates.


The point is to support *all* arithmetic types, including user-defined
ones.
Again, why?
>
>Further, getting good results from numeric computations means writing
type-specific code -- it varies depending on the details of the type.
You can't, in general, write it generically.


I write arithmetic generic code all the time -- all you need is a robust
understanding of integer promotion and conversion.
But your example function only makes sense for floating-point types.
Even if you want to throw in int or long, why in the world do you need
to calculate forces for char, unsigned char, and signed char?

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
Sep 23 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.