I would like to write a "portable" C++ library in Clang. "Portable" means that I detect (in C preprocessor) what C++ features are available in the compilation environment and use these features or provide my workarounds. This is similar to what Boost libraries are doing.
However, the presence of some features depends not on the language, but on the Standard Library implementation. In particular I am interested in:
type traits (which of them are available and with what spelling)
if initializer_list being constexpr.
I find this problematic because Clang by default does not use its own Standard Library implementation: it uses libstdc++. While Clang has predefined preprocessor macros __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, they are hardcoded to values 4, 2, 1 respectively, and they tell me little about the available libstdc++ features.
How can I check in Clang preprocessor what version of libstdc++ it is using?
Clang does come with its own standard library implementation, it's called libc++. You can use it by adding -stdlib=libc++ to your compile command.
That being said, there are various ways to check Clang/libstdc++ C++ support:
Clang has the __has_feature macro (and friends) that can be used to detect language features and language extenstions.
Libstdc++ has its own version macros, see the documentation. You'll need to include a libstdc++ header to get these defined though.
GCC has its version macros which you already discovered, but those would need to be manually compared to the documentation.
And also, this took me 2 minutes of googling.
This is what I think would help. It prints the value of the _LIBCPP_VERSION macro:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, const char * argv[])
{
cout<<"Value = "<<_LIBCPP_VERSION<<endl;
return 0;
}
Compile it again the version of clang you want the info for.
Related
I have found many questions to this topic but all problems seem to be related to not compiling with C++ 11. My code is
#include <random>
int main(int argc, char *argv[]){
std::default_random_engine generator;
return 0;
}
even though I compile with
gcc -std=c++0x testmain.cpp
Giving the error that default_random_engine is not a member of std. The program is compiled on a remote machine, which I do not maintain myself but
gcc -v
yields a version of 4.4.7.
Any ideas?
For others:
Check if you actually include random with #include <random>. I didn't have it and some other header included it previously. Now that header got updated and I got this error and didn't find it for a while because I was checking compiler settings.
As DevSolar already stated, your gcc version is too old, to support this C++11 feature.
It was added in gcc-4.5:
Improved experimental support for the upcoming ISO C++ standard,
C++0x, including:
Support for <future>, <functional>, and <random>.
Reference: https://gcc.gnu.org/gcc-4.5/changes.html
This is also reflected by the libstdc++ API Reference: https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.5/a01118.html
where you can find the following:
typedef minstd_rand0 default_random_engine
Your code works fine for me in: gcc-5.1.0, gcc-4.9.2 and clang-3.7.0,
Also you should use the command: g++ instead of gcc so gcc links against proper c++ libraies by default.
Your problem is you're not compiling with C++11. ;-) (Sorry, could not resist.)
GCC 4.4.7 is dated March 2012. C++11 support was not yet complete in that version.
As of the time of this writing, the current version of GCC is 5.2.0... which is C++14 compliant. Time to update your compiler. ;-)
I hate to recommend this but in your case (old untouchable machine) I can offer a suggestion. The tr1 version of the random library should be available for g++-4.4:
#include <tr1/random>
int main(int argc, char *argv[]){
std::tr1::default_random_engine generator;
return 0;
}
There have been improvements in the std version relative to tr1 version but you should be able to use most <random> features.
You don't even need C++0x.
I am trying to compile a library using clang. The library makes calls to 'unlink', which is not defined by clang:
libmv/src/third_party/OpenExif/src/ExifImageFileWrite.cpp:162:17: error: use of undeclared identifier 'unlink'; did you mean 'inline'?
unlink( mTmpImageFile.c_str() ) ;
My question is, what is the clang equivalent of unlink? As I see it, the path forward would be to #define unlink somewhere with an equivalent routine.
There is no "Clang equivalent". Neither GCC nor Clang have ever been responsible for defining unlink, though they do probably distribute the POSIX headers which do (I don't recall specifically where POSIX headers come from).
Unfortunately, this appears to be a bug with the library you're using; the OpenExif developers failed to include the correct headers. Different C++ implementations may internally #include various headers for their own purposes, which has apparently masked this bug on your previous toolchain.
You can hack your copy and/or submit a patch to add:
#include <unistd.h>
I'm trying to compile a program I wrote in linux on Xcode and for my random functions I used:
std::random_device seed_device;
std::default_random_engine engine(seed_device());
But default_random_engine won't compile on Xcode. Is there a different version I should use?
You need to #include <random>.
In general, when the compiler complains about "no type named function_name in namespace std", you have to check that:
You have included the right header. You can look up the name of the right header on any decent C++ reference.
Your standard library supports C++1x (*) (or, at least, the feature you want).
Your compiler supports C++1x (*) (or, at least, the feature you want), and the right flags are used to enable it, if required.
(*) The x stands for the version of the C++ standard that includes the feature you want.
The following simple code can't be compiled by g++ 4.3:
#include <array>
using namespace std;
int main()
{
std::array<int, 8> myarray;
return 0;
}
array: No such file or directory
Also, the compiler doesn't seen to understand option '-std=c++11' as is recommended to provide to the compiler. Is there another option?
Thanks.
GCC 4.3 and presumably also your C++ library are too old for the support you're looking for. You need a newer version. Here's a link to the GCC C++11 support page, and another link to the libstdc++ C++11 support page.
Alternatively, clang supports all of C++11 with libc++.
For me the problem was that it was a cross compiler that needed to be told where the sysroot was, and supplying --sysroot=<path to sysroot> allowed GCC to find the headers
I'd like to use unordered_set without installing Boost. I tried to add --std=gnu++0x but it is not a recognized option. Does v4.1.2 include unordered_set? If so, how do I get the header file for it?
This is a Centos 4 machine.
unordered_set is in the purview of the standard C++ library, not gcc, the compiler (although most programs built using gcc are linked against libstdc++).
The way you generally include it is #include <tr1/unordered_set>. Then, to use it, you must either do a using std::tr1::unordered_set; or qualify the name each time.
The C++ standard version you choose to use doesn't have much effect because that's the language standard, and the availability of standard library constructs is semi-independent.
IIRC, gcc-4.2 did not have unordered containers at least not in namespace std. I know -std=c++0x was not in place till around gcc-4.3.
Have you tried this:
#include <tr1/unordered_set>
...
std::tr1::unordered_set<int> usint;
...
Notice the tr1/ in the header.
Having said that, gcc-4.1 is pretty old. Any chance you could try say gcc-4.5 or 4.6 and use the std container?