How can we know which operating system the code is running?
e.g.
How to know the operating system like Unix-Linux, Solaris, HP Unix, Windows, Mac etc?
How can we determine operating system in C++ code with boost?
I want to test with Boost v1.41 onwards.
These are things a quick scan of version.hpp/config.hpp revealed:
Live On Coliru
#include <boost/version.hpp>
#include <boost/config.hpp>
#include <iostream>
int main() {
std::cout << "BOOST_VERSION " << BOOST_VERSION << "\n";
std::cout << "BOOST_LIB_VERSION " << BOOST_LIB_VERSION << "\n";
std::cout << "BOOST_PLATFORM " << BOOST_PLATFORM << "\n";
std::cout << "BOOST_PLATFORM_CONFIG " << BOOST_PLATFORM_CONFIG << "\n";
std::cout << "BOOST_COMPILER " << BOOST_COMPILER << "\n";
#ifdef BOOST_LIBSTDCXX_VERSION
std::cout << "BOOST_LIBSTDCXX_VERSION " << BOOST_LIBSTDCXX_VERSION << "\n";
#endif
#ifdef BOOST_LIBSTDCXX11
std::cout << "Compiled with c++11 support enabled\n";
#endif
std::cout << "BOOST_STDLIB " << BOOST_STDLIB << "\n";
std::cout << "BOOST_STDLIB_CONFIG " << BOOST_STDLIB_CONFIG << "\n";
}
Which prints
BOOST_VERSION 106400
BOOST_LIB_VERSION 1_64
BOOST_PLATFORM linux
BOOST_PLATFORM_CONFIG boost/config/platform/linux.hpp
BOOST_COMPILER Clang version 3.8.0 (tags/RELEASE_380/final 263969)
BOOST_STDLIB libc++ version 1101
BOOST_STDLIB_CONFIG boost/config/stdlib/libcpp.hpp
Or on my own machine
BOOST_VERSION 106500
BOOST_LIB_VERSION 1_65
BOOST_PLATFORM linux
BOOST_PLATFORM_CONFIG boost/config/platform/linux.hpp
BOOST_COMPILER GNU C++ version 7.2.0
BOOST_LIBSTDCXX_VERSION 70200
Compiled with c++11 support enabled
BOOST_STDLIB GNU libstdc++ version 20170818
BOOST_STDLIB_CONFIG boost/config/stdlib/libstdcpp3.hpp
Code must be compiled to the specific platform you're targeting so you must know the platform at compile time. For example Linux binaries can't be run on BSD, Solaris, AIX... so checking the OS at runtime makes no sense and is useless
That means the OS needs to be checked via preprocessor directives and not in a C statement. There's Boost.Predef which contains various predefined macros for determining the platform
This library defines a set of compiler, architecture, operating system, library, and other version numbers from the information it can gather of C, C++, Objective C, and Objective C++ predefined macros or those defined in generally available headers. The idea for this library grew out of a proposal to extend the Boost Config library to provide more, and consistent, information than the feature definitions it supports. What follows is an edited version of that brief proposal.
...
BOOST_ARCH_ for system/CPU architecture one is compiling for.
BOOST_COMP_ for the compiler one is using.
BOOST_LANG_ for language standards one is compiling against.
BOOST_LIB_C_ and BOOST_LIB_STD_ for the C and C++ standard library in use.
BOOST_OS_ for the operating system we are compiling to.
BOOST_PLAT_ for platforms on top of operating system or compilers.
BOOST_ENDIAN_ for endianness of the os and architecture combination.
BOOST_HW_ for hardware specific features.
BOOST_HW_SIMD for SIMD (Single Instruction Multiple Data) detection.
You can use BOOST_OS_* and BOOST_PLAT_* for your purpose. For example
#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/os.h>
#if BOOST_OS_WINDOWS
#elif BOOST_OS_ANDROID
#elif BOOST_OS_LINUX
#elif BOOST_OS_BSD
#elif BOOST_OS_AIX
#elif BOOST_OS_HAIKU
...
#endif
The full list can be found in BOOST_OS operating system macros and BOOST_PLAT platform macros. BOOST_HW_ can also be used to detect the hardware platform
Demo on Godbolt
See also demo on BOOST_ARCH
Related
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.
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?
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";
}
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
this is the code i am trying to compile, got it from another forum somewhere.
// to_string example
#include <iostream> // std::cout
#include <string> // std::string, std::to_string
int main ()
{
std::string pi = "pi is " + std::to_string(3.1415926);
std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
std::cout << pi << '\n';
std::cout << perfect << '\n';
return 0;
}
I am getting the error:
'to_string' is not a member of 'std'
I have read in other forums to select the flags "Have g++ follow the c++11 ISO language standard [-std=c++11]" and i have and it still doesn't work.
Any help would be greatly appreciated
I am using the GNU GCC Compiler
and code::Blocks 12.11
MinGW-w64 added support for the necessary functionality since GCC 4.8, so make sure you are using at least version 4.8 GCC from MinGW-w64.
You can get one from here, although Code::Blocks should come with a TDM GCC toolchain which should work if it's the latest (because it's GCC 4.8.1 at the time of writing).
i also encounter this error in codeblocks-13.12mingw-setup-TDM-GCC-481.exe(built on 27 Dec 2013).
it seems a bug with tdmgcc4.8.1. maybe the newest tdmgcc whill fixed it.
https://stackoverflow.com/questions/21626866/c-elipse-cdt-getting-to-string-was-not-declared-in-this-scope-with-tdm-gcc-6
the reason of above list should be the same as ours.
==============================
The std::to_string functions are guarded by !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF). MinGW defines this symbol as 1 in its os_defines.h, so you know, we cannot use it in mingw.
Easiest way to deal with this error is:
double piValue = 3.1415;
char piBuffer[8];
sprintf(piBuffer, "%f", piValue);
string pi(piBuffer);