My understanding is that the function std::isnan is only available from C++11 onwards. Further, g++ uses -std=gnu++98 unless specifically told not to.
So why does this compile?
>> cat test.cpp
#include <cmath>
int main(int argc, char** argv)
{
return std::isnan(0);
}
>> g++ test.cpp
Is there a flag to take the function out of <cmath>?
Compiler developers are lazy about exactly removing every feature that should only be available in the next version of the standard, especially when related libraries (C99) have it at the same time.
The utility (of validing your code actually obeys a specific standard) is not high enough for compiler writers to work extremely hard at making their compiler provide that service.
Instead, what usually happens is new features are implemented under specific standard flags. Sometimes they are accidentally backported. When the standard finalizes, the partial implementation exists for a while until it gets good enough.
Then work starts on the next version of the standard. The next version flag gives you a less stable development environment, as new features are tried out and discarded and changed.
Some effort it put into not backporting stuff, but it isn't a showstopper.
This is a long-standing issue, documented in the FAQ but in a way that you wouldn't necessarily be able to make sense of.
4.3. _XOPEN_SOURCE and _GNU_SOURCE are always defined?
On Solaris, g++ (but not gcc) always defines the preprocessor macro _XOPEN_SOURCE. On GNU/Linux, the same happens with _GNU_SOURCE. (This is not an exhaustive list; other macros and other platforms are also affected.)
These macros are typically used in C library headers, guarding new versions of functions from their older versions. The C++98 standard library includes the C standard library, but it requires the C90 version, which for backwards-compatibility reasons is often not the default for many vendors.
More to the point, the C++ standard requires behavior which is only available on certain platforms after certain symbols are defined. Usually the issue involves I/O-related typedefs. In order to ensure correctness, the compiler simply predefines those symbols.
Note that it's not enough to #define them only when the library is being built (during installation). Since we don't have an 'export' keyword, much of the library exists as headers, which means that the symbols must also be defined as your programs are parsed and compiled.
To see which symbols are defined, look for CPLUSPLUS_CPP_SPEC in the gcc config headers for your target (and try changing them to see what happens when building complicated code). You can also run g++ -E -dM - < /dev/null" [sic] to display a list of predefined macros for any particular installation.
This has been discussed on the mailing lists quite a bit.
This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time.
To explain:
glibc is what provides the standard C library. It supports several modes.
It supports various strict C modes and strict POSIX modes. In these modes, when only standard headers are included, only standard functions are available. In C90 mode, this does not include isnan.
It supports various extension modes. In these modes, non-standard functions are also available. In C90 + extensions mode, this includes isnan. The _GNU_SOURCE preprocessor macro is the one that enables all extensions.
libstdc++ is what provides the standard C++ library. It requires more from glibc than what strict C90 mode offers. Therefore, there are only two options: either libstdc++ does not offer those standard C++ features it cannot provide, or libstdc++ forcibly enables glibc's extensions even in strict ANSI mode. Both mean a failure to conform to the C++ standard, but the former restricts features, while the latter provides them. The latter is seen as the lesser evil.
The only reasonable way to fix this is for glibc to provide some non-standard way to access its extensions even in strict ANSI mode. No such way exists yet, and until such a way is created, non-standard names will be available even in meant-to-be-standard C++ compilation modes.
Related
Suppose we have a shared library which accepts or returns some kind of std class:
//lib.h
#include <vector>
std::vector<int> returnSomeInts();
//lib.cpp
#include "lib.cpp"
std::vector<int> returnSomeInts() {
return {1, 3, 5};
}
So, obviously, when compiling the shared library lib.so, this code had to be compiled against a particular version of the standard library, for instance with -std=c++11.
Now imagine we have an application which will be using our shared library, but it will be compiled against a newer std library, for example -std=c++2a
//app.cpp
#include <lib.h>
int main()
auto v = returnSomeInts();
//Process v
}
As the standard library defines inline classes, if the layout of the class members changes, ABI compatibility gets broken, so the code above would not work properly.
My questions are: Is there any guarantee for ABI stability with the common implementations of the the std library when compiling against the same header using different c++ standards? And when compiling against different header versions (libstdc++-8 and libstdc++-9 for example)?
PD: The code above is just an example, I am not referring specifically to std::vector
ABIs in practice are not linked to the standard, for example consider this following code compiled with gcc 4.9.4 and gcc 5.1
using the same flags:
-std=c++11 -O2
#include <string>
int main(){
return sizeof (std::string);
}
gcc 4.9.4 returns 8 from main, gcc 5.1 returns 32.
As for guarantees: it is complicated:
Nothing is guaranteed by the standard.
Practically MSVC used to break ABI compatability, they stopped (v140,v141,v142 use the same ABI), clang/gcc have a stable ABI for a long time.
For those interested in learning more:
For a broad discussion of ABI/C++ standard that is not directly related to this question you an look at this blog post.
Your example with std::vector is not a problem. As other answer points out compilers maintain compatibility and std::vector is quite old.
Problem can be new library features of newer C++ standard is used.
For example I have some product which uses C++17 languages features. My product supports MacOS 10.13. I can build my project using C++17 (language features), but I can't use for example std::optional since some methods are throwing std::bad_optional_access which is part dynamic library and this is not supported/present in MacOS 10.13. Clang warns me about that (reports an error).
Same applies on other system (clang nicely controls that). So when you use some library features you need make sure that libraries on deployed system supports that (on Linux package managers handle that nicely if system doesn't have access to required package version installation will fail). On Windows 10 AFAIK Windows update keeps newest version of msvc redistributable, older versions of Windows need manual updates.
Note that many templates are becoming part of your executable and do not have dependencies to shared standard library. Those will not create problems.
These are the kinds of question that the standard doesn't answer, it is down to individual implementers how long they keep compatibility for and which (if any) compiler flags affect compatibility.
In practice libstdc++ on Linux has tried very hard to keep a stable ABI for quite a long time now. The soversion has remained at 6 for around 15 years now.
However there have been some changes, most notable were those introduced with g++-5.1 related to std::list and std::string. New requirements in c++11 meant that to be compliant libstdc++ needed to make breaking changes to the ABI of those classes.
g++'s solution was to define two versions of those classes. To allow both types to coexist in the same shared library they are defined with different names, so the old std::list is defined as std::list while the new std::list is defined as std::__cxx11::list and then aliased as std::list. Which definition is used in a given source file is controlled by a preprocessor macro.
Note that the setting of said preprocessor macro is independent of the -std= setting, you can use the compiler in c++11 mode with the old string/list implementation (in which case it won't be fully compliant with the standard) or you can use the compiler in c++03 mode with the new string/list implementations.
The default value of the macro (if not set explicitly by the user) depends on compiler version and can also be overridden by distribution maintainers.
The trouble is while this solves the problem for libstdc++ it doesn't solve it for all the other libraries. If a program was built with the new implementations while a library was built with the old ones or vice-versa and the library used std::string or std::list in it's API, then the likely outcome was a link failure (it was also possible but less-likely for the linking to succeed but the program to be silently broken). In Debian at least this lead to a massive set of library transitions (it would not surprise me if it was the largest in the project's entire history).
Is it possible to enforce a C or C++ language standard for just part of a source file? I want to ensure that my source file is C90 compliant, but it depends on some headers that require C99. The compliance of those headers isn't important to me right now (I can compile with C99 for the time being), but I want to minimize effort required to port my code to a more restrictive platform in the future.
In short, I want a language standard to apply to the entire file except for the included headers. Given how header inclusion works in C and C++, I figure that the general problem is to apply a language standard to an arbitrary portion of a given source file.
I'm working with GCC in particular, but I'm also curious if this is possible with other compilers (msvc, clang).
If you want to make sure your code is C90 compatible while still relying on headers that use C99, you can enable the GCC warning flag -Wc90-c99-compat. This allows you to use C99 features, but emits a warning wherever you use features not available in C90. To avoid generating these warnings in your header files (which are presumably correct), enable the warning using a pragma, after you include the files.
This will basically achieve what you want. The warnings will only be emitted for the code you specify.
#include "myheader.h"
#pragma GCC diagnostic warning "-Wc90-c99-compat"
void func(void) { ... }
A stricter version would be to use:
#pragma GCC diagnostic error "-Wc90-c99-compat"
As far as I know, Clang is mostly compatible, but MSVC doesn't really support C99 that well to begin with so you're on your own.
No. You cannot build a file (compilation unit) as partly one language standard and partly another.
What you can do however is split the file into two files and compile each of them using different language standards (just be sure that it is then still well defined to link both object files afterwards).
A better solution would be to ensure that all the code complies with the newer or older language standard and then just use that.
I am wondering something for which I have not found a convincing answer yet.
Situation:
A system with some libraries (e.g. gtkmm) compiled without c++11 enabled.
An application compiled with C++11 enabled.
Both are compiled and linked with the same GCC version/environment.
The application has some function calls to the library which use std::string and std::vector.
both std::string and std::vector support move semantics which most likely mean they are not binary compatible with wth non C++11 variants. However both the application and library are build with the same compiler and standard libraries, so it would not be so strange if the lib would recognize this and support it.
Is the above situation safe, or would it be really required to compile everything with the C++11 flag, even if the same build environment is used ?
This page is dedicated to g++ abi breaks with c++11 up to version 4.7.
The first sentence there is:
The C++98 language is ABI-compatible with the C++11 language, but several places in the library break compatibility. This makes it dangerous to link C++98 objects with C++11 objects.
Though there are examples, where enabling c++11 won't brake ABI compatibility: one example is Qt where you can freely mix c++11 enabled builds with c++03 builds.
You can consider each translation of C++ by a different compiler (even if the compiler is the same, but has a different (minor) version) incompatible. C++ has no common application binary interface (ABI).
In addition, a change of the dialect supported by the compiler is a change of the ABI, hence the resulting libraries are incompatible. An obvious example is a release build vs. debug build, where the debug data structures introduce additional members.
And moving structures (C++11) or not moving structures ( < C++11) is a radical change of the ABI.
I'm currently using gcc 4.8.2 with no std option to compile my c/c++ code.
Now I would like to use some of the new C/C++ features that are provided by the newer language versions of c/c++.
(Un?)Fortunately gcc understands many flavors of C/C++:
c90, c99, c11, gnu90, gnu99, gnu11
c++98, c++03, c++11, gnu++98, gnu++03, gnu++11
Currently I'm asking myself:
Do I need for every c/c++ version a separate library or is it possible to use one library for multiple C/C++ versions?
Especially can I link a libary compiled with a specific c/c++ version, when I use the corresponding c/c++-version with the gnu extensions?
Clarification (based on the comments)
Please note, that I'm using just one compiler. Not two gcc's that only differ in the revision number.
I'm only asking for ABI incompatibilities between the different std-options, when using only one gcc compiler.
In general:
No you can't combine different language versions in the same program, this will cause "One Definition Rule" violations in many library headers.
You may find in limited cases that a few classes actually don't change with the language version. However this is rare, rvalue references are required by the C++11 Standard, and not available in C++03 mode at all.
As for versions with and without support for GNU extensions, you're likely to have more success, but you will still need to run each header through the preprocessor and verify that the exact same sequence of tokens is seen by the compiler using both options.
And that's completely apart from ABI changes, that could cause memory layout or name mangling to differ between compiler variants.
You can also avoid one-definition rule violations on your own public APIs by avoiding using any version and language-specific features. Essentially, this means a flat C API.
What is a good way of checking for the presence of specific C++11 features of the standard library.
For compiler features I just went by the way of checking the compiler version for the (IMHO) major compilers (VC++, gcc, clang at the moment, maybe Intel) Although this is not the best and most flexible approach, I don't know of anything better yet, except for clang which has the really nice __has_feature macros.
But it's even worse for library features, which are not coupled that rigidly to the compiler. At the moment I want to use the same approach of checking the compiler version for VC++ (where it's pretty easy, assuming it uses its own library). For clang I can at least use __has_include for large-scale header-based queries. Other than that I guess checking __GLIBCXX__'s value if defined might be a good idea, but then again I cannot find any information of what specific libstdc++ versions introduced which features, other than what the current version supports.
The methods should be kept to preprocessor checks and the like, since I want to use it in a header-only library without any sophisiticated configure procedure and without using any third-party libraries (and yes, boost is third-party).
So what are my possibilities of checking for specific C++11 library features under those (pretty narrow) conditions. Maybe even on the scale of particular functions or types being declared?
If checking for the compiler or library version is still the best approach, where can I find detailed information about the particular C++11 features supported by a specific version of libstdc++ (and maybe other important ones, libc++ perhaps)?
FWIW at the moment I'm interrested in <cstdint>, C++11 <cmath> functions and std::hash, but this may change and is probably not of importance for the general approach.
There is really nothing nice you can do here besides knowing which compiler in which version implements what and have the proper defines in place.
gcc has a special table for library functionality. The main problem of __has_include are of course additions to the standard that live in old includes. libstdc++ also has the necessary includes, but that doesn't mean the necessary define to enable the content of those files. It also wont tell you anything about the actual amount of available implementation (which sometimes is incomplete).
As you have a header-only library this doesn't apply to you, but is still important: binary incompatibility between C++11 and C++03 can come back and bite you.
I seriously wouldn't approach any of that on my own and rather use Boost.Config. Originally it only described language features but has now expanded to standard library headers.
You could write autoconf macros to check, and if you do, submit them to http://www.gnu.org/software/autoconf-archive/
The only relevant one so far checks for complete coverage, not for individual features: http://www.gnu.org/software/autoconf-archive/ax_cxx_header_stdcxx_0x.html#ax_cxx_header_stdcxx_0x
But that fails the requirement for no complicated configure checks.
Other than that I guess checking __GLIBCXX__'s value if defined might be a good idea,
Looking at the value of __GLIBCXX__ is not useful, it contains the date the version was released which tells you almost nothing about the version (e.g. 4.6.3 is released after 4.7.0 so has a later date in __GLIBCXX__ but has fewer C++11 features.) When using libstdc++ with GCC you want to use the general GCC version numbers in __GLIBC__ and __GLIBC_MINOR__ for checking versions (in general you can only use a given version of libstdc++ with the GCC release it came with.)
Edit: Starting with GCC 7 there is a new macro defined by the libstdc++ headers, _GLIBCXX_RELEASE, which is defined to the same value as GCC's __GNUC__, but is still usable even when using the libstdc++ headers with non-GCC compilers.
but then again I cannot find any information of what specific libstdc++ versions introduced which features, other than what the current version supports.
The libstdc++ C++11 status tables for previous releases are available online where all GCC docs live: http://gcc.gnu.org/onlinedocs/
For 4.7 it's at http://gcc.gnu.org/onlinedocs/gcc-4.7.1/libstdc++/manual/manual/status.html#status.iso.2011 and for 4.6 it's at http://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/manual/manual/status.html#status.iso.200x and for previous releases is included with the source (but the coverage in pre-4.6 releases is pretty patchy anyway.)
Some added features are listed in the release notes for each version, e.g. http://gcc.gnu.org/gcc-4.7/changes.html (in the libstdc++ section)
Edit: For C++17 library support we now list which version first added the feature, so you only need to look at the latest docs: https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.201z
FWIW at the moment I'm interrested in <cstdint>, C++11 <cmath> functions and std::hash
They should be present in all versions of libstdc++ that have any C++0x/C++11 support.