Re: cstdlib declarations of ::abs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 5 March 2017 at 22:42, Dave Gittins wrote:
> Hi,
>
> I have a question about the intended declarations of ::abs in gcc when
> we #include <cstdlib>.
>
> I am aware that the standard does not require cstdlib to provide any
> declaration of ::abs at all, and that compliant code should either use
> std::abs, or #include <stdlib.h> (deprecated) before using ::abs. So,
> I expected cstdlib to either:
> 1. not provide ::abs at all, or
> 2. provide all the overloads of abs (::abs(int), ::abs(long),
> ::abs(long long)) - the same set that are required to be provided if
> we include <stdlib.h>
>
> In practice, using gcc 5.4.0/6.3.0 on both OSX 10.10.5 and Fedora Core
> 17 (glibc 2.15), I was surprised to find that including cstdlib
> provides only ::abs(int), as per the C library spec. It therefore
> seems easy to end up calling ::abs(int) with a long by mistake if you
> mistakenly believe stdlib.h was included. (I realise that -Wconversion
> would also catch this).

<cstdlib> doesn't add anything to the global namespace. The C library
defines ::abs(int) and then <cstdlib> adds std::abs(int),
std::abs(long) and std::abs(long long).

> I'm not suggesting this is an error, for the reasons above. My question is:
>  - Is this intentional behaviour?

Yes.

>  - If not, is it possible/useful to change it to one of the above?

Option 1 isn't practically possible, and the intention had been not to
do option 2. <cstdlib> adding things to the global namespace is icky,
but I suppose the C library already does that, and arguably
consistently icky would be better than inconsistently icky.

It could be considered an extension of LWG 2294 which says that all
the integral and floating point overloads are declared by both <cmath>
and <cstdlib>, so that only including one doesn't allow you to
accidentally call std::abs and trigger an unwanted conversion from
floating point to integral, or vice versa (and correspondingly for
<math.h> and <stdlib.h> with calls to ::abs).

Your option 2 would mean that all of the std::abs and ::abs overloads
are declared by any of <cmath>, <cstdlib>, <math.h> or <stdlib.h>.

That would be easy to do on trunk because they're all in one place
now, in a new internal header:

--- a/libstdc++-v3/include/bits/std_abs.h
+++ b/libstdc++-v3/include/bits/std_abs.h
@@ -105,6 +105,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
+
+using std::abs;
 }

 #endif // _GLIBCXX_BITS_STD_ABS_H

But I don't see why this should be restricted to abs. If you include
<cmath> and then call ::sin with a long double you get the
::sin(double) overload, which loses precision. Unless we say that
*every* overloaded function in <cstdlib> and <cmath> always gets
dumped into the global namespace this problem still exists. Including
the right headers for what you use really is the best solution. If you
always use the <cxxx> header and qualify names with std:: then the
problem doesn't exist.

> I also looked at the behaviour of #include <stdlib.h>, which AFAIK is
> required to provide all the overrides of ::abs, and on my test systems
> it does indeed do that with gcc 6.3.0 (since bug 60401 was fixed).

Right.

> Also just for information, with llvm 3.9.0 clang++/libc++, #include
> <cstdlib> and #include <stdlib.h> both seem to provide all the
> overloads of ::abs.



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux