Where is isnan() in MSVC 2010? - c++

I'm trying to write a program which uses std::isnan() with MSVC 2010. I include cmath but unfortunately the compiler returns the error:
isnan is not part of the std namespace
Does MSVC 2010 support this function from std (AKA C++11)?

std::isnan is in <cmath> : http://en.cppreference.com/w/cpp/numeric/math/isnan
Your problem is probably VS2010 which has very poor C++11 support. I'd recommend grabbing VS2015 which is much better in that regard.
As can be seen here VS2010 only has _isnan .

Unfortunately, Visual Studio's C++11 support hasn't been that complete until the 2015 version, so you won't be able to utilize the C++ std::isnan functionality. Interestingly, there is a C99 isnan macro, but it's implementation defined and VS 2010 does not seem to have any of those macros. Fortunately though, the MS line of compilers do have their MS specific _ versions of the _isnan functionality. So you could write your own isnan as such:
#include <iostream>
#include <cmath>
#include <cfloat>
#include <limits>
namespace non_std
{
template < typename T >
bool isnan(T val)
{
#if defined(_WIN64)
// x64 version
return _isnanf(val) != 0;
#else
return _isnan(val) != 0;
#endif
}
}
int main(int argc, char** argv)
{
float value = 1.0f;
std::cout << value << " is " <<
(non_std::isnan(value) ? "NaN" : "NOT NaN") << std::endl;
if (std::numeric_limits<float>::has_quiet_NaN) {
value = std::numeric_limits<float>::quiet_NaN();
std::cout << value << " is " <<
(non_std::isnan(value) ? "NaN" : "NOT NaN") << std::endl;
}
return 0;
}
On my machine this produces the output:
1 is NOT NaN
1.#QNAN is NaN
Note that the _isnanf is for 64-bit applications and the _WIN64 macro might not necessarily be defined, so if you target 64 bit be sure to adjust that.
Hope that can help.

Related

How to check if C++ 2011 is enabled on Microsoft and Intel compilers?

I was pretty sure that the compiler is supposed to define __cplusplus such that it indicates which version of the C++ standard is being parsed.
But compiling the following code
#include <iostream>
#include <vector>
int main(int argc, char **argv)
{
const int cxx_version = __cplusplus;
std::cout << "C++ version: " << cxx_version << std::endl;
std::vector<int> v(100, 2);
int s = 0;
for(auto i : v) {
s += i;
}
std::cout << "Sum: " << s << std::endl;
return 0;
}
with
cl cxx11.cpp /Qstd=c++11
or
icl cxx11.cpp /Qstd=c++11
with both Visual Studio 2013 and Intel C++ 16.0 on Windows, produces the unexpected result
C++ version: 199711
Sum: 200
As we can see, the range-based for loop works as expected, but __cplusplus should have been 201102, right?
So my question is three-fold:
Is /Qstd=c++11 the correct way to enable C++ 2011 on Microsoft or Intel compiler on Windows?
Is __cplusplus the correct think to check the language version based on the C++ standard? Is there a more reliable alternative for standards-compliant compilers?
Is there a reliable check for either the Microsoft or Intel compilers in Windows?

Right aligning money_put results

I'm trying to get the C++ library to generate properly formatted USD output ($ sign, commas for every 1000s place etc).
I'm close, but I cannot get the right alignment to work:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
locale myloc;
const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
cout.imbue(myloc);
cout << showbase << fixed;
cout << "A";
cout.width(30);
cout.setf(std::ios::right);
mpUS.put(cout, false, cout, ' ', fiftyMil * 100); // convert to cents
cout << "B" << endl;
return 0;
}
I'm getting:
A$50,000,000.00 B
I want to get:
A $50,000,000.00B
Any ideas why this isn't working?
I'm using the latest Solaris compiler (12.4)
Update:
It seems like the issue is with the C++ libraries included with the Solaris compiler. This is the workaround I used:
#include <iostream>
#include <iomanip>
#include <locale>
#include <sstream>
using namespace std;
string getFormattedCcy(double amt) {
ostringstream os;
static locale myloc;
static const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
os.imbue(myloc);
os << showbase << fixed;
mpUS.put(os, false, os, ' ', amt * 100);
return os.str();
}
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
cout << "A";
cout.setf(std::ios::right);
cout.width(30);
cout << getFormattedCcy(fiftyMil);
cout << "B" << endl;
return 0;
}
You have a couple of problems--one with your code, another that looks like its in your implementation.
The problem in your code is pretty trivial. Since you're using a default-constructed locale, it should be using the "C" locale, which shouldn't write out the $ or thousands separators.
That part is easy to fix. Change: locale myloc; to: locale myloc(""); to get a localized locale (so to speak).
I doubt that'll fix the justification problem you're seeing though. That looks to me like it's a problem with the standard library you're using. When I run your code (with the correction above) I get what I'd expect:
A $50,000,000.00B
That's with Visual C++ though (and despite a compiler that conforms fairly poorly, its standard library is about as good as they come).
Also note that right justification is the default, so the line:
cout.setf(std::ios::right);
...should have no effect (but I suspect you knew that, and added it in the hope of getting it to work when it didn't otherwise).
As far as how to get things to work with the Sun Oracle compiler, the most obvious suggestion would probably be to switch standard libraries to one that works better. That leads to another question: whether to try to get a standard library to work with the compiler you're using, or switch to a different compiler such as CLang or gcc. From what I understand, 12.4 was a pretty serious improvement in terms of C++ conformance, but I don't think either the compiler or (apparently) the standard library is really competitive with gcc or Clang yet. OTOH, you may not have a choice, in which case essentially your only route is to build a different standard library with your existing compiler, and hope for the best. If you can't even do that...you could try setting the locale correctly, and just writing the number with std::cout << fiftyMil;, and hope it at least gives you commas as it should, then add the currency sign separately.
As an aside, if you do get an updated (C++11 or newer) library, you can use put_money to simplify the code quite a bit:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
std::locale myloc("");
cout.imbue(myloc);
cout << "A" << showbase << setw(30) << put_money(fiftyMil * 100) << "B";
}

Is <cmath> or <math.h> really needed? Compiles without it

So, I have the following code, and it builds and runs perfectly, tried various values and all is well. You'll notice I use log10 function and I do not include cmath or math.h. Why does it still build and run fine? Are those libraries really needed? Why/Why not? Does it have anything to do with me using visual studio? Like, would it not compile if say I was using a different IDE or command prompt to compile it?
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Classify solutions as acidic or nonacidic" << endl<< endl;
//declaring double molar concentration
double mc = 1;
//using while and if statements to calculate pH in fixed notaion and acidic or nonacidic
while (mc != 0)
{
cout << "Please enter a molar concentration (or enter 0 to exit): ";
cin >> mc;
if (mc != 0)
{
cout << "Molar Conentration = " << scientific << mc << endl; //scientific notation
double pH = -log10(mc);
cout << "pH = " << fixed << setprecision(6) << pH << endl; //6 deciumals
if (pH > 7)
{
cout << "Nonacidic" << endl << endl;
}
else if (pH < 7)
{
cout << "Acidic" << endl << endl;
}
else
cout << "Neutral" << endl << endl;
}
}
//end program when inputing 0
cout << "End of Program" << endl;
return 0;
}
The code:
i = i++ + ++i;
may also compile okay, but that doesn't make it a good idea :-)
It would be wise to include headers for library functions that you use. You don't lose any functionality by doing so but you do guarantee the functionality will work (misuse notwithstanding).
Detailed analysis follows.
Even if an implementation is relaxed about this, the standard mandates it. C++11 17.6.2.2 Headers /3 states:
A translation unit shall include a header only outside of any external declaration or definition, and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
The gcc compiler, for example, will grumble bitterly about your code:
xyzzy.cpp: In function 'int main()':
xyzzy.cpp:22:34: error: 'log10' was not declared in this scope
double pH = -log10(mc);
^
As to why VC++ seemingly violates this rule, it has to do with the fact that header files are allowed to include other header files.
If you compile your code to produce pre-processor output (with /P), you'll find a line buried deep within it thus (at least in VS2013):
#line 1 "c:\\blah\\blah\\vc\\include\\cmath"
And a bit of analysis turns up the following hierarchy of includes:
iostream
istream
ostream
ios
xlocnum
cmath
(<xlocnum>, one of the internal headers used by <locale>, appears to need ldexp() from the <cmath> library, though there may be others as well).
That's further evidenced by the fact that VC++ does complain about the following code:
//#include <iostream>
using namespace std;
int main() {
double oneHundred = 100;
int two = log10 (oneHundred);
return two;
}
with:
error C3861: 'log10': identifier not found
but that error disappears the instant you uncomment the iostream inclusion line.
However, as previously stated, that is not behaviour you should rely on. If you are going to use a library function (or macro/template/whatever), it's up to you to include the correct header.
Otherwise your program compiling correctly is simply an accident.
As you've noticed, the code snippet you provided works in Visual Studio but not with other compilers. This is because of how the standard library is implemented for each compiler.
It turns out that when you include Visual Studio's implementation of <iostream>, you end up including a bunch of other headers indirectly, and one of these headers is <cmath>.
To see the exact chain, navigate to the standard library include directory. For me (I use Visual Studio 2013 Community Edition) this is located at
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include
Open iostream. Note the line #include <istream>
Open istream. Note the line #include <ostream>
Open ostream. Note the line #include <ios>
Open ios. Note the line #include <xlocnum>
Open xlocnum. Note the line #include <cmath>
Guess what? You included cmath when you included iostream... so your code is good to go, on Visual Studio at least. But, don't rely on implementation details or your code will break if you try to migrate it to another platform/toolchain.
For example, trying to compile the provided snippet using g++ on Cygwin results in the following error:
temp.cpp: In function ‘int main()’:
temp.cpp:22:34: error: ‘log10’ was not declared in this scope
double pH = -log10(mc);
This must mean g++'s implementation of <iostream> doesn't depend on <cmath>

stdint.h not compatible with C++?

I tried to compile a source code package, and found version-specific issues.
When I do that on my computer, everything goes well; but when I compile it on another computer, it produces a lot of claims that INT32_MAX is not defined. Both computer runs a Debian system, and the difference is my computer uses Testing repo and has gcc 4.9, and the other computer uses Stable repo., which has slightly older gcc 4.7.
Then I have a detailed look inside /usr/include/stdint.h. By surprise, on the computer claiming the undefined macros, all int range macros are defined inside a non-C++ condition:
/**
* I forget the exact definition,
* but it looks like this:
*/
#ifndef __cplusplus ......
......
# define INT32_MIN XXX
# define INT32_MAX XXX
......
#endif
As a result, the package won't see these standard range macros, as it is a C++ project, and uses g++ to compile.
Why the stdint.h of gcc 4.7 is designed like this? Is that means gcc 4.7 don't want me to use those integer ranges with C++, and gcc 4.9 allows it?
And the most important: how should I work around this?
In C++ you're recommended to use std::numeric_limits #include <limits>:
Usage example from cplusplus.com
// numeric_limits example
#include <iostream> // std::cout
#include <limits> // std::numeric_limits
int main () {
std::cout << std::boolalpha;
std::cout << "Minimum value for int: " << std::numeric_limits<int>::min() << '\n';
std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << '\n';
std::cout << "int is signed: " << std::numeric_limits<int>::is_signed << '\n';
std::cout << "Non-sign bits in int: " << std::numeric_limits<int>::digits << '\n';
std::cout << "int has infinity: " << std::numeric_limits<int>::has_infinity << '\n';
return 0;
}
Include climits or limits.h that contains sizes of integral types. This header defines constants with the limits of fundamental integral types for the specific system and compiler implementation used. The limits for fundamental floating-point types are defined in cfloat ( earlier float.h). The limits for width-specific integral types and other typedef types are defined in cstdint (earlier stdint.h).
You should include cstdint instead of stdint.h

Avoiding compiler issues with abs()

When using the double variant of the std::abs() function without the std with g++ 4.6.1, no warning or error is given.
#include <algorithm>
#include <cmath>
double foobar(double a)
{
return abs(a);
}
This version of g++ seems to be pulling in the double variant of abs() into the global namespace through one of the includes from algorithm. This looks like it is now allowed by the standard (see this question), but not required.
If I compile the above code using a compiler that does not pull the double variant of abs() into the global namespace (such as g++ 4.2), then the following error is reported:
warning: passing 'double' for argument 1 to 'int abs(int)'
How can I force g++ 4.6.1, and other compilers that pull functions into the global namespace, to give a warning so that I can prevent errors when used with other compilers?
The function you are using is actually the integer version of abs, and GCC does an implicit conversion to integer.
This can be verified by a simple test program:
#include <iostream>
#include <cmath>
int main()
{
double a = -5.4321;
    double b = std::abs(a);
double c = abs(a);
std::cout << "a = " << a << ", b = " << b << ", c = " << c << '\n';
}
Output is:
a = -5.4321, b = 5.4321, c = 5
To get a warning about this, use the -Wconversion flag to g++. Actually, the GCC documentation for that option explicitly mentions calling abs when the argument is a double. All warning options can be found here.
Be warned, you don't need to explicitly #include <cmath>, <iostream> does the damage as well (and maybe some other headers). Also, note that -Wall doesn't give you any warnings about it.
#include <iostream>
int main() {
std::cout << abs(.5) << std::endl;
std::cout << typeid(decltype(abs)).name() << std::endl;
}
Gives output
0
FiiE
On
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04)