How do I test for a version of the libstdc++ - c++

So I was deep in the depths of my code writing an erase method for my container class when I went to call std::vector::erase with a const_iterator and if failed mightily. Just like it did for this person.
Following the links to gnu libstdc++ status shows that this issue has still not been fixed (the original question was early 2013).
So I coded up a horrible hack-around:
#if 1
// horrible hack for gnu libstd++ deficit
// current implementation does not allow erase(const_iterator), so recreate plain iterator
off_t::iterator itx= offsets_.begin() + ( apos.iter() - offsets_.begin() ) ;
#else
// for compliant implementations
auto itx= apos.iter() ;
#endif
But I am wondering if there is #define I can use the relates to the version of libstdc++. There are plenty to test for the version of the compiler, but I don't think that gcc versions are going to be a good indicator for when this is fixed, and since clang uses the same library by default I need to catch it either way. I took a look at the output of g++ -E -dM - < /dev/null but the only ones that even mentioned STD didn't seem to promising:
#define __STDC_HOSTED__ 1
#define __STDC_IEC_559__ 1
#define __STDC_ISO_10646__ 201103L
#define __STDC_NO_THREADS__ 1
#define _STDC_PREDEF_H 1
#define __STDC_IEC_559_COMPLEX__ 1
#define __STDC__ 1

Won't you be on the hook with clang anyway? If it's fixed by the gcc distribution, is it guaranteed to be fixed by clang and visa versa? How about the other compilers?
You can obtain a list of compiler defines
For example
#define __GNUC_PATCHLEVEL__
#define __GNUC__
#define __GNUC_MINOR__
or for clang
#define __clang__
#define __clang_major__
#define __clang_minor__
#define __clang_patchlevel__
Do you use autotools? If so, then since you're thinking of macro-ing yourself out of this situation anyway, you can create an autotools test to create your own define. The test doesn't need to compile, in fact that typically IS the test.

Related

How do I test the version of libstdc++, not GCC, at compile time?

I am trying to test the version of libstdc++ because std::regex is implemented, but largely broken, in the versions of libstdc++ distributed with GCC before version 4.9.0.
Note that:
I need to test the version of libstdc++, not GCC because Clang also supports using libstdc++ as the standard library. This rules out testing the __GNUC_PATCHLEVEL__, __GNUC__, and __GNUC_MINOR__ macros.
The __GLIBCXX__ macro is a date, not a version number and does not increase monotonically. For example, GCC 4.8.4 ships with #define __GLIBCXX__ 20150426, which is newer than the release date of GCC 4.9.0.
Is there any portable way to test the version of libstdc++ that does not depend on using GCC my compiler?
In my opinion the problem is sufficiently small to be solved by brute force.
In a header file called machine.hpp or similar I would test that the version of the C++ Standard is at least what I need it to be (the __cplusplus macro). Then I would add the various macro checks to reject any library that I know to be flawed.
In other words, I would take a black-list approach instead of a white-list approach.
For example:
#pragma once
#ifndef MACHINE_HPP_HEADER_GUARDS
#define MACHINE_HPP_HEADER_GUARDS
#if __cplusplus < 201103L
// Library is incompatible if it does not implement at least the C++11
// standard.
#error "I need a library that supports at least C++11."
#else
// Load an arbitrary header to ensure that the pre-processor macro is
// defined. Otherwise you will need to load this header AFTER you
// #include the header you care about.
#include <iosfwd>
#endif
#if __GLIBCXX__ == 20150422
#error "This version of GLIBCXX (20150422) has flaws in it"
#endif
// ...repeat for other versions of GLIBCXX that you know to be flawed
#endif // MACHINE_HPP_HEADER_GUARDS

Clang compiles code in GCC define block [duplicate]

I am working on a project that has been built with both gcc and msvc so far. We recently started building with clang as well.
There are some parts in the code, where platform-specific things are done:
#ifndef _WIN32
// ignore this in msvc
#endif
Since gcc has previously been the only non-windows build, this was equivalent to saying "do this only for gcc". But now it means "do this only for gcc and clang".
However there are still situations, where I would like to handle something specifically for gcc, and not for clang. Is there a simple and robust way to detect gcc, i.e.
#ifdef ???
// do this *only* for gcc
#endif
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.
Also:
__GNUG__
The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).
Source
Apparently, clang uses them too. However it also defines:
__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__
So you can do:
#ifdef __GNUC__
#ifndef __clang__
...
Or even better (note the order):
#if defined(__clang__)
....
#elif defined(__GNUC__) || defined(__GNUG__)
....
#elif defined(_MSC_VER)
....
I use this define:
#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__))
And test with it:
#if GCC_COMPILER
...
#endif
With Boost, this becomes very simple:
#include <boost/predef.h>
#if BOOST_COMP_GNUC
// do this *only* for gcc
#endif
See also the Using the predefs section of the boost documentation.
(credit to rubenvb who mentioned this in a comment, to Alberto M for adding the include, and to Frederik Aalund for correcting #ifdef to #if)

Printing the c++ compiler name

I have been working with qt creator and recently tried to change the compiler from gcc to clang. Since I don't get any info (or can't see it) on whether this worked (I'm struggling to understand the interface) I wanted to ask if there's a way for my c++ code to print out the compiler under which it's being compiled.
Compilers set certain #defines to help out with things like this.
In your case,
#ifdef __GNUC__ //GCC
//do whatever GCC-specific stuff you need to do here
#endif
#ifdef __clang__ //clang
//do whatever clang-specific stuff you need to do here
#endif
This page on SourceForge shows a list of such compiler-specific #define values.
EDIT: as pointed out in the comments, clang sets __GNUC__, and possibly __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. You might be better off using a double test to make sure clang isn't misleading you:
#if defined(__GNUC__) && !defined(__clang__)
//do whatever GCC-specific stuff you need to do here
#endif
Use the informational macros of boost.
#include <boost/config.hpp>
#ifdef BOOST_CLANG
printf("Successfully changed to clang\n");
#endif

Where is __MWERKS__ in OS10.7?

In Photoshop CS2 SDK file SPConfig.h, the follow code get error.Obviously I needed the define of __MWERKS__. The Compiler is LLVM GCC 4.2, the SDK is OS X 10.7 .
#ifdef __MWERKS__
#if !defined(__INTEL__) /* mjf was- #if defined(__MC68K__) || defined(__POWERPC__) */
#ifndef MAC_ENV
#define MAC_ENV 1
#endif
#endif
#endif
#if !defined(WIN_ENV) && !defined(MAC_ENV)
#error
#endif
In file cdefs.h:
#if defined(__MWERKS__) && (__MWERKS__ > 0x2400)
I want to know how to find where it defines. Or can I just define a number to it?
Those macros are defined by the compiler itself to indicate which compiler it is (so you can write compiler-specific things).
__MWERKS__ was used by Metrowerks CodeWarrior, which was discontinued in 2005, so is slightly obsolete by now.
You should not define it yourself - unless you're compiling with CodeWarrior, those parts should be skipped, or the program will most likely break in unpredictable ways.
Your actual problem is that your compiler & SDK combination isn't recognized as a Macintosh environment.
There must be some other place that defines MAC_ENV.
(I find it hard to believe that the CS2 SDK wouldn't support Apple's own compiler.)
You should go search for all occurrences of MAC_ENV.
Are you sure that the combination of SDKs and compiler you're using is supported?
The CS2 SDK is so old it might not be, so you should also read the documentation carefully.

Determine C++0x availability

I'm trying to determine if C++0x features are available when compiling. Is there a common preprocessor macro? I'm using Visual Studio 2010's compiler and Intel's compiler.
The macro __cplusplus will have a value greater than 199711L.
That said, not all compilers will fill this value out. Better to use Roger's solution.
The usual way to do this is determine it in the build system, and pass "configuration macros", commonly named HAS_*, when compiling. For example: compiler -DHAS_LAMBDA source.cpp.
If you can determine this from compiler version macro, then you can define these macros in a configuration header which checks that; however, you won't be able to do this for anything controlled by a command-line option. Your build system does know what options you specify, however, and can use that info.
See boost.config for a real example and lots of details about specific compilers, versions, and features.
We've had similar problems with nullptr and auto_ptr. Here's what we're trying to use until somehing is standardized:
#include <cstddef>
...
// GCC: compile with -std=c++0x
#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5))
# define HACK_GCC_ITS_CPP0X 1
#endif
#if defined(nullptr_t) || (__cplusplus > 199711L) || defined(HACK_GCC_ITS_CPP0X)
# include <memory>
using std::unique_ptr;
# define THE_AUTO_PTR unique_ptr
#else
# include <memory>
using std::auto_ptr;
# define THE_AUTO_PTR auto_ptr
#endif
It works well on GCC and Microsoft's Visual Studio. By the way, nullptr is a keyword and can't be tested - hence the reason for the nullptr_t test.