I'm including <cmath> but can't compile std::abs(double) - c++

After re-installing Rad-Studio XE2 I'm finding that some code that used to compile no longer works. For example I get a compiler error on the following:
#include <cmath>
void MyClass::Rotate(double RotAngle){
bool NotRotated = std::abs(RotAngle) < 1;
... do something
}
with the following error:
[BCC32 Error] XXX.cpp(38): E2015 Ambiguity between 'std::abs(int) at c:\program files (x86)\embarcadero\rad studio\9.0\include\windows\crtl\stdlib.h:142' and 'std::abs(__int64) at c:\program files (x86)\embarcadero\rad studio\9.0\include\windows\crtl\stdlib.h:538'
This code used to compile, and obviously should, so what am I missing? Rad_studio has had all updates applied..

In this case we actually can learn a lot from the standard.
C++98: In 26.5/Table 80 and 81 we learn that abs is in <cstdlib> and NOT <cmath>. But then in 26.5 we have the contradictory statement In addition to the double versions of the math functions in <cmath>, C++ adds float and long
double overloaded versions of these functions, with the same semantics. which then lists abs as having additional overloads in <cmath> where the preceeding table said it should not be.
This is actually fixed in C++11 where 26.8/Table 119 clearly shows abs as a member of <cmath> as well as in <cstdlib> (although the added overloads for floating point types still appear exclusive to <cmath>.
As for your problem there are two likely situations:
You were compiling as C++11 before and are no longer doing so.
You were compiling C++98/03 but your standard libraries were updated to a version where <cmath> no longer implicitly includes <cstdlib> and your compiler was based on the table requirements rather than the implicit requirements of 26.5.
Most likely including <cstdlib> would fix the problem as would compiling in C++11 mode.

Related

‘numeric_limits’ is not a member of ‘std’

I am trying to compile an application from source, FlyWithLua, which includes the sol2 library.
I am following the instructions but when I run cmake --build ./build I get the following error:
In file included from /home/jon/src/FlyWithLua/src/FloatingWindows
/FLWIntegration.cpp:10:
/home/jon/src/FlyWithLua/src/third_party/sol2/./upstream/sol.hpp: In lambda function:
/home/jon/src/FlyWithLua/src/third_party/sol2/./upstream/sol.hpp:7194:59:
error: ‘numeric_limits’ is not a member of ‘std’
7194 | std::size_t space = (std::numeric_limits<std::size_t>::max)();
There are several other errors on the same line after this, but I guess they might just go away if I can solve this one.
there are several similar issues with the solution to add the following includes to the .hpp file
#include <stdexcept>
#include <limits>
the sol.hpp file includes the following imports:
#include <stddef.h>
#include <limits.h>
https://sol2.readthedocs.io/en/latest/errors.html gives some hints about the why the compiler might not recognize these includes:
Compiler Errors / Warnings
A myriad of compiler errors can occur when something goes wrong. Here
is some basic advice about working with these types:
If there are a myriad of errors relating to std::index_sequence, type traits,
and other std:: members, it is likely you have not turned on your C++14 switch for
your compiler. Visual Studio 2015 turns these on by default, but g++ and clang++
do not have them as defaults and you should pass the flag --std=c++1y or
--std=c++14, or similar for your compiler.
the src/CMakeList.txt file has the following line:
set(CMAKE_CXX_STANDARD 17)
I'm only faintly familiar with C/C++ and this all seems very complicated to me, but I'm hoping that there might be an easily recognizable cause and solution to this to someone more skilled.
cat /etc/*-release gives
DISTRIB_RELEASE=21.10
DISTRIB_CODENAME=impish
DISTRIB_DESCRIPTION="Ubuntu 21.10"
$ g++ --version
g++ (Ubuntu 11.2.0-7ubuntu2) 11.2.0
/home/jon/src/FlyWithLua/src/third_party/sol2/./upstream/sol.hpp:7194:59:
error: ‘numeric_limits’ is not a member of ‘std’
7194 | std::size_t space = (std::numeric_limits<std::size_t>::max)();
This error message implies that src/third_party/sol2/./upstream/sol.hpp header uses std::numeric_limits, but also that std::numeric_limits hasn't been defined. The simplest explanation for that is that the header that defines std::numeric_limits hasn't been included. In such case, the solution is to include the header that defines std::numeric_limits.
the sol.hpp file includes the following imports:
#include <stddef.h>
#include <limits.h>
This confirms the problem. Neither of those headers define std::numeric_limits.
https://sol2.readthedocs.io/en/latest/errors.html gives some hints about the why the compiler might not recognize these includes:
Those hints may apply to some other cases, but not this one. std::numeric_limits has been part of the C++ standard since the beginning, so language version has no effect on its existence.
Conclusion: According to the quoted error message, sol.hpp uses std::numeric_limits which is defined in the header <limits>, but according to you, it doesn't include that header. If this is the case, then this is a bug in the sol.hpp file. Correct solution would be to fix the sol.hpp file by including <limits> in that file before using std::numeric_limits.

Missing include gives no compile error on RedHat 6

This snippet can not be compiled, since std::accumulate is found in the header numeric, which is not included.
#include <algorithm>
#include <vector>
int main () {
std::vector<int> vec{ 1, 2, 3, 4 };
return std::accumulate(vec.begin(), vec.end(),0);
}
The compiler explorer gives me the correct error message
<source>(6): error: namespace "std" has no member "accumulate"
return std::accumulate(vec.begin(), vec.end(),0);
I am using RedHat 6 and the intel compiler version 18.0.3. If I compile it with this setting, I get no error and the result is fine. No warning is shown, even if -Wall is used.
My question is, why don't I get an appropriate error message?
why don't I get an appropriate error message?
Because one of the standard library headers <algorithm> or <vector> that you use for compilation do include <numeric> themselves. This is a common portability issue; your code happens to compile with a particular standard library implementation, but fails to build with another one. Library implementations are free to include standard headers in standard headers. Maybe some functionality in your <algorithm> was implemented using any of the <numeric> algorithms, and there you are.
The compiler error you encounter is the reason tools like include-what-you-use exist. Using iwyu her would add #include <numeric> to your snippet. Note also that no warning flags will influence the result of the compilation. Either you get a hard compiler error or nothing.

Include Order and Hidden Dependencies

While looking for best pratices regarding include order, I was stumbling over this thread:
C/C++ include file order/best practices [closed]
#squelart was stating, that it is better pratice to include from local to global, as this reduces the chance of hidden dependencies. I just tested this in a VS2015 project with the following code:
StrTest.h
#pragma once
class CStrTest
{
public:
CStrTest();
~CStrTest();
std::string test;
};
StrTest.cpp
#include <string>
#include "StrTest.h"
CStrTest::CStrTest()
{
}
CStrTest::~CStrTest()
{
}
I couldn't reproduce the stated behaviour (hidden dependencie duo including string first in StrTest.cpp). The compiler gives me mulitple errors. So is this something out of the past or did I overlook something?
EDIT: VS2015 Compiler errors:
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int
Error C2039 'string': is not a member of 'std'
Error C3646 'test': unknown override specifier
So is this something out of the past
No, the hidden dependencies are the standard behaviour and do happen in modern compilers. I don't know of VS, but GCC and Clang do compile your shown program without any errors. Demo: https://wandbox.org/permlink/ATJndwrOwirpDgDd
The compiler gives me mulitple errors.
Although an "implicit" include is poor style, it is still technically well formed as far as the standard is concerned as long as the implicitly included file is guaranteed to be included by you or whoever wrote the header that includes it - standard headers have no such guarantees.
Therefore I would be against such compiler feature that considers implicit includes as errors. An explicitly enable-able warning would be much more suitable.
I think the point of hidden dependence problem discussed there is that typically each file includes several other files and if header is not self-contained then including it may work in cases when it's implicit dependences are included by some other header and break everything when those other headers change and / or get moved / removed. In short: use of headers with hidden dependencies lead to extremely fragile code.
// foo.hpp
#pragma once
#include <string> // if we remove this unrelated `StrTest.h` header will be broken
...
.
// main.cpp
#include "foo.hpp" // if we move this one line lower `StrTest.h` header will be broken
#include "StrTest.h" // accidentally works fine
...

C++11 exit() and abs() without including <cstdlib>?

Please tell me why this code is compiled with C++11 standard:
#include <iostream>
using namespace std;
int main()
{
abs(-12);
exit(1);
return 0;
}
it is without error g++ -std=++11 main.cpp
this error g++ main.cpp
if you remove #include <iostream> then get the error on exit() and abs() when the program is compiled.
Tell me why this happens, if I don't include <cstdlib>? And how to do that would compile with -std=c++11 was a warning or error?
The answer is really simple: the code compiles because under C++11 your iostream lib includes other libraries that have exit() and abs() defined. You won't get a warning or error for that. Why would you? After all cascade includes are supported.
However you should not depend on that since that's not a part of the standard and may break under different compiler. But I guess that as long as you stick to one compiler and one -std flag you're fine. Also fixing this by adding some includes should not be a big deal as well.

-O1/2/3 with -std=c++1y/11/98 - If <cmath> is included i'm getting error: '_hypot' was not declared in this scope

I've just updated MinGW using mingw-get-setup and i'm unable to build anyting that contains <cmath> header if I use anything larger than -O0 with -std=c++1y. (I also tried c++11 and c++98) I'm getting errors like this one:
g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3 -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
from Z:\Projects\C++\L6\src\utils.h:4,
from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
Is something wrong on my side?
Or version at mingw repo is bugged? And if so, is there any quick fix for this header?
To avoid any further speculation, and downright bad suggestions such as using #if 0, let me give an authoritative answer, from the perspective of a MinGW project contributor.
Yes, the MinGW.org implementation of include/math.h does have a bug in its inline implementation of hypotf (float, float); the bug is triggered when compiling C++, with the affected header included (as it is when cmath is included), and any compiler option which causes __STRICT_ANSI__ to become defined is specified, (as is the case for those -std=c... options noted by the OP). The appropriate solution is not to occlude part of the math.h file, with #if 0 or otherwise, but to correct the broken inline implementation of hypotf (float, float); simply removing the spurious leading underscore from the inline reference to _hypot (float, float), where its return value is cast to the float return type should suffice.
Alternatively, substituting an equivalent -std=gnu... for -std=c... in the compiler options should circumvent the bug, and may offer a suitable workaround.
FWIW, I'm not entirely happy with MinGW.org's current implementation of hypotl (long double, long double) either; correcting both issues is on my punch list for the next release of the MinGW runtime, but ATM, I have little time to devote to preparing this.
Update
This bug is no longer present in the current release of the MinGW.org runtime library (currently mingwrt-3.22.4, but fixed since release 3.22). If you are using anything older than this, (including any of the critically broken 4.x releases), you should upgrade.
As noted by Keith, this is a bug in the MinGW.org header.
As an alternative to editing the MinGW.org header, you can use MinGW-w64, which provides everything MinGW.org provides, and a whole lot more.
For a list of differences between the runtimes, see this wiki page.
MinGW uses gcc and the Microsoft runtime library. Microsoft's implementation support C90, but its support for later versions of the C standard (C99 and C11) is very poor.
The hypot function (along with hypotf and hypotl) was added in C99.
If you're getting this error with a program that calls hypot, such as:
#include <cmath>
int main() {
std::cout << std::hypot(3.0, 4.0)) << '\n';
}
then it's just a limitation of the Microsoft runtime library, and therefore of MinGW. If it occurs with any program that has #include <cmath>, then it's a bug, perhaps a configuration error, in MinGW.