25

Here lists the current overloads of std::abs in C++. I'm wondering why not just define the following template and let go all the ugly C-style overloads?

template <typename T> inline
T abs(const T& v) { return v < 0 ? -v : v; }
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
Lingxi
  • 14,579
  • 2
  • 37
  • 93

3 Answers3

22

See LWG issue 2192. Currently, std::abs(x-y) < 2 fails if x and y are unsigned. This catches a subtle programming error. With the proposed change, it compiles but does entirely the wrong thing. abs(3u-4u) would be much larger than 2, in fact it's UINT_MAX.

Patrik
  • 2,695
  • 1
  • 21
  • 36
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • @MohitJain `0u - 1u == UINT_MAX`, and `UINT_MAX == 2^(whatever) - 1`. – Quentin Apr 02 '15 at 12:00
  • 2
    That is a great example and issue 2192 is an interesting read. – Shafik Yaghmour Apr 02 '15 at 12:43
  • Well, `std::abs(3u - 4u)` compiles. See http://www.cplusplus.com/reference/cmath/abs/. – Lingxi Apr 02 '15 at 13:28
  • Still, I do not get it why the overloads for integral types return a `double` instead of the original integral type. – Lingxi Apr 02 '15 at 13:33
  • @Lingxi: Wrong page? http://www.cplusplus.com/reference/cstdlib/abs/ . Or look at a better site: http://en.cppreference.com/w/cpp/numeric/math/abs – MSalters Apr 02 '15 at 13:37
  • It's counter-intuitive to me that the overloads for signed integral types are put in `` other than ``. I just thought that all math functions are put int the latter header. – Lingxi Apr 02 '15 at 13:58
  • @Lingxi: That's another issue, [LWG 2294](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2294) – MSalters Apr 02 '15 at 14:03
11

This suffers the usual problem of matching everything.

An example of a type for which abs makes sense but this implementation does not is complex<double>.

  • 3
    There is an `std::abs` overload for complex numbers that would be found by overload resolution and preferred, since it is more specialized (in terms of partial ordering) than the above. – Columbo Apr 02 '15 at 11:21
  • @Columbo: it does answer the question why you can't eliminate _all_ current overloads. – MSalters Apr 02 '15 at 11:23
  • @MSalters Well you could specialise the template for Complex. – Neil Kirk Apr 02 '15 at 11:25
  • 3
    @Columbo: The point isn't that `complex` won't work as is: the point is to demonstrate the definition in the OP can be flat out wrong for reasonable types. Similar user-defined types would fail to compile (or worse, silently compile a *wrong* implementation). –  Apr 02 '15 at 11:28
  • @Hurkyl I didn't try to criticize your answer anyway, that was more of a side-note - this template and overloads for e.g. `complex` go together quite well :) – Columbo Apr 02 '15 at 11:29
  • It gets to a point where you can't protect the user from calling functions they don't understand. – Neil Kirk Apr 02 '15 at 11:31
  • @NeilKirk:That specialization would be a partial specialization (`std::complex` itself is a template) and you cannot partially specialize functions - precisely because you can have overloads. – MSalters Apr 02 '15 at 11:34
  • @Hurkyl What you said also applies to `std::swap`. It do not think it is a problem. – Lingxi Apr 02 '15 at 11:34
  • @Hurkyl But you do answer why we should live with the overloads :) – Lingxi Apr 02 '15 at 11:38
  • This could be solved [with a little bit of ADL](http://codereview.stackexchange.com/q/60140/15094) injected into the function. – Morwenn Apr 02 '15 at 14:07
  • But aren't these problems similar for std::less? If you feed it with rubbish you get rubbish. – gast128 Mar 20 '19 at 10:21
1

Because type 'T' can access any data type including char. So what are you expecting if someone will pass a char to the abs function. :)

Nihar
  • 347
  • 2
  • 16
  • 9
    The same as for int, except it will only be 8-bits. – Neil Kirk Apr 02 '15 at 11:15
  • yes @NeilKirk you are correct as c++ will do a ascii value manipulation we will get a result . But that is not a output what an end user want. – Nihar Apr 02 '15 at 11:17
  • 3
    No, C++ won't do an " ASCII" manipulation. it will without a doubt do a numerical manipulation. The biggest issue in fact would be that `char` may be unsigned, which would give rather unexpected results (!) – MSalters Apr 02 '15 at 11:19
  • It's common to use char types to hold 8-bit data as, well, there isn't any alternative, at least not in the past. Performing abs on `char` would be of questionable usefulness however, as its signness is implementation defined. – Neil Kirk Apr 02 '15 at 11:20