std::abs problem

J

John Doe

If I include <cmath> and write std::abs in my program I get:

gcc -MD -o /home/bla/c++/.build/generator.o -c
generator.cpp
generator.cpp: In function 'int main(int, char**)':
generator.cpp:206: error: call of overloaded 'abs(unsigned int)' is
ambiguous
/usr/include/gentoo-multilib/amd64/stdlib.h:786: note: candidates are:
int abs(int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cstdlib:143: note:
long int std::abs(long int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cstdlib:173: note:
long long int __gnu_cxx::abs(long long int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:90: note:
double std::abs(double)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:94: note:
float std::abs(float)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:98: note:
long double std::abs(long double)
make: *** [/home/bla/c++/.build/generator.o] Error 1

The problem is there is no templated std::abs(), like there is
std::max(). Do I do:

template <class T>
T abs(T const& in)
{
return std::max(-in, in);
}

or something like that? Maybe there's a more beautiful solution? Perhaps
there's something in boost?
 
V

Victor Bazarov

John said:
If I include <cmath> and write std::abs in my program I get:

gcc -MD -o /home/bla/c++/.build/generator.o -c
generator.cpp
generator.cpp: In function 'int main(int, char**)':
generator.cpp:206: error: call of overloaded 'abs(unsigned int)' is
ambiguous
/usr/include/gentoo-multilib/amd64/stdlib.h:786: note: candidates are:
int abs(int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cstdlib:143:
note: long int std::abs(long int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cstdlib:173:
note: long long int __gnu_cxx::abs(long long int)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:90: note:
double std::abs(double)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:94: note:
float std::abs(float)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/include/g++-v4/cmath:98: note:
long double std::abs(long double)
make: *** [/home/bla/c++/.build/generator.o] Error 1

The problem is there is no templated std::abs(), like there is
std::max(). Do I do:

template <class T>
T abs(T const& in)
{
return std::max(-in, in);
}

or something like that? Maybe there's a more beautiful solution?
Perhaps there's something in boost?

I think you're missing the simple fact that you're trying to get
an absolute value of an *unsigned* expression. There is no need to
do that. There are no negative unsigned ints. If you *have to*
specialise 'std::abs' for 'unsigned', you're free to do so:

namespace std { template<> abs(unsigned int u) { return u; } }

But then again, perhaps you need to read the error message a bit more
carefully and consider *why* you're trying to find an absolute value
of an unsigned int expression...

V
 
J

John Doe

But then again, perhaps you need to read the error message a bit more
carefully and consider *why* you're trying to find an absolute value
of an unsigned int expression...

It's you who is in error, as the difference of 2 unsigned numbers may
well be negative. Here's the line from my program:

std::abs(n - m);

where we are subtracting unsigned ints. The result may well turn
negative and what then?
 
J

John Doe

Ah no, you were right and me wrong/ignorant

If during the evaluation of an expression, the result is not
mathematically defined or not in the range of rep-
resentable values for its type, the behavior is undefined, unless such
an expression is a constant expression
(5.19), in which case the program is ill-formed. [Note: most existing
implementations of C++ ignore integer
overflows. Treatment of division by zero, forming a remainder using a
zero divisor, and all floating point
exceptions vary among machines, and is usually adjustable by a library
function. ]

So what I was doing was undefined.
 
V

Victor Bazarov

John said:
It's you who is in error, as the difference of 2 unsigned numbers may
well be negative.

Not in C++.
Here's the line from my program:

std::abs(n - m);

where we are subtracting unsigned ints. The result may well turn
negative and what then?

I think you're mistaken. The result of any arithmetic operation between
two values of type 'unsigned' is of type 'unsigned'.

V
 
V

Victor Bazarov

John said:
Ah no [..]

So what I was doing was undefined.

No, the type 'unsigned' behaves as if every operation is modulo 2^bits
where 'bits' is the number of bits in the representation.

V
 
K

kwikius

Not in C++.




I think you're mistaken. The result of any arithmetic operation between
two values of type 'unsigned' is of type 'unsigned'.

Aha.. Another bullet point for my "Don't use unsigned unless you
really have to" armory !

:)

regards
Andy Little
 
J

John Doe

Aha.. Another bullet point for my "Don't use unsigned unless you
really have to" armory !

Hah, no, you've gotta read the standard and familiarize yourself with
it. The more it bites the better.
 
J

John Doe

No, the type 'unsigned' behaves as if every operation is modulo 2^bits
where 'bits' is the number of bits in the representation.

Where did ya find that, the only thing I could come up had to do with
the unary(!) - operator:

The operand of the unary - operator shall have arithmetic or enumeration
type and the result is the negation of its operand. Integral promotion
is performed on integral or enumeration operands. The negative of an
unsigned quantity is computed by subtracting its value from 2^n , where
n is the number of bits in the promoted operand. The type of the result
is the type of the promoted operand.

m - n is a binary operation.
 
G

Gavin Deane

Where did ya find that, the only thing I could come up had to do with
the unary(!) - operator:

Fundamental Types
3.9.1/4
Unsigned integers, declared unsigned, shall obey the laws of
arithmetic modulo 2^n where n is the number of bits in the value
representation of that particular size of integer.

and its footnote:
This implies that unsigned arithmetic does not overflow because a
result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting unsigned integer type.

The footnote talks about what happens if the result is greater than
the largest value that can be represented, but the implication is
similar for <0.

Gavin Deane
 
K

kwikius

Hah, no, you've gotta read the standard and familiarize yourself with
it. The more it bites the better.

Certainly seems to have bitten you! ... :)

regards
Andy Little
 
J

John Doe

and its footnote:
This implies that unsigned arithmetic does not overflow because a
result that cannot be represented by the resulting unsigned integer
type is reduced modulo the number that is one greater than the largest
value that can be represented by the resulting unsigned integer type.

The footnote talks about what happens if the result is greater than
the largest value that can be represented, but the implication is
similar for <0.

3 different places in the standard for the same thing is, I think,
still ok.
 
D

Diego Martins

Not in C++.




I think you're mistaken. The result of any arithmetic operation between
two values of type 'unsigned' is of type 'unsigned'.


in VS 2005 , the result of difference of two shorts gave me an int :(

why?

Diego
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top