4

Possible Duplicate:
How do I check for C++11 support?

I am writing a small library and I would like to use class enums whenever the compiler supports them. I also want to use other C++11 features, such as final and override keywords.

So far, I have used tricks to make sure it compiled on all versions of GCC, but I when I booted my Windows partition, Visual Studio 2010 started complaining too. Here is an example of the tricks I used:

#if __GNUC__ == 4 && (__GNUC_MINOR__ > 7 || \
      (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ > 1))
#   define TATO_OVERRIDE override
#   define TATO_NO_THROW nothrow
#else
#   define TATO_OVERRIDE
#   define TATO_NO_THROW throw()
#endif

I know that the newest version of Visual Studio already supports a batch of new features too. What I would like to have, is something like a set of macro which tells me what features are available on the compiler I am using.

#ifdef THIS_COMPILER_SUPPORTS_CLASS_ENUMS
  ...
#endif

Does this exist? Is there a library that does that?


The compiler’s documentation?

Let me clarify. I know how to find those information, my problem is elsewhere. I don’t want to go through every possible compiler’s documentation to gather those information, especially since the same compiler might support different features with respect to its version. This is what I have been doing so far, and what I am looking for is actually a way not to do that.

Community
  • 1
  • 1
qdii
  • 12,505
  • 10
  • 59
  • 116
  • 1
    The compiler's documentation? – Austin Henley Oct 10 '12 at 14:26
  • I think you will have to check `__cplusplus` is bigger than something. My compiler (VS2008) does not support c++11 and its value is 199711. So check if it is bigger than 199711. – tozka Oct 10 '12 at 14:29
  • 3
    `Boost.Config` could be somewhat helpful (http://stackoverflow.com/a/5047980/276274) – Maksim Skurydzin Oct 10 '12 at 14:37
  • @tozka Doesn't work either, since VC10 supports many (or rather *"some"*) C++11 features, yet doesn't define `__cplusplus` to the value for C++11 (`2011..`), I'm not even sure they define it to `199711` and not just to `1` or something the like. Same for VC11, I think. On the other hand I wouldn't want to miss those features by going an all-or-nothing path (since even gcc 4.7 with its definition of `__cplusplus` to `2011..` doesn't support the whole standard yet). – Christian Rau Oct 10 '12 at 14:41
  • [`BOOST_NO_SCOPED_ENUMS`](http://www.boost.org/doc/libs/1_51_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_c__11_features_not_supported) – Benjamin Lindley Oct 10 '12 at 14:45

4 Answers4

4

Boost actually has a wide range of such macros available. You could use that. Otherwise, the only way is to essentially check the compiler's version and use your knowledge of the features supported in that version to decide if a feature is available or not.

Essentially, what Boost does, except manually.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
3

There were discussions of having some standardized feature test mechanism but it turns out that this doesn't make any sense: If a compiler implements the standard, all feature tests would yield true. If it doesn't there is no reason to assume that it follows the standard in terms of the feature tests!

Thus, using some sort of configuration file seems to be the most reliable approach. Personally, I would do it differently than explicitly checking for compiler versions: instead, I would use something trying whether a compiler supports a specific feature to an acceptable degree. The configuration could be run in terms of autoconf or something similar.

With respect to the resulting configuration I would try to map things to suitable constructs and not use conditional compilation outside the configuration headers. For example, I would use something like this:

#if defined(KUHL_HAS_CLASS_FINAL)
#  define kuhl_class_final final
#else
#  define kuhl_class_final
#endif

Specifically for class enums you might need to use something a bit tricky because the enumeration values will only be available within a scope while the values are only available outside a scope. Thus, it may be necessaray to come up with some form of extra nesting in one case but not the other.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 1
    @Dietman - Re: 'it turns out that this doesn't make any sense'. This isn't accurate. Standard could dictate that compilers implement __has_xxxx macro when xxxx is implemented. Source can #ifdef for the feature, and get false when feature isn't implemented (compilers have to do nothing when feature isn't implemented). – Uri London Oct 10 '12 at 15:06
  • @Uri - There are at least two problems here: 1. If the compiler isn't fully conformant, how do we know that *this* feature is supported? 2. Some committee members don't want to make it easier to deliver a subset of the language, they want it ALL - a complete C++11 implementation. So no concensus on which macros, if any, should be defined. – Bo Persson Oct 10 '12 at 16:12
  • @Uri: if any of the feature tests could possibly be false you *know* that the implementation isn't conforming. If it isn't conforming why would you assume it conforms on the feature tests? It may not bother or even give false answers! "but the standard says ..." is pointless for non-conforming tests. If you want a feature test in a conforming compiler, here is the universal test you can query to find if a mandatory feature is supported: `true` – Dietmar Kühl Oct 10 '12 at 16:30
  • 2
    @Dietmar et al: the "how do you know conformance on the feature test" argument is a fallacy. it's not at all difficult to define feature macros so that if that macro is not defined, it indicates lacking feature. thus as features get implemented, all the compiler vendor has to do is to define the appropriate macros. the fallacy is the old "i can't imagine how it could work, and since i'm interested in it not working i can only see ungood ways to do it, and hence it cannot work". in short, an example of a silly failure to open door, e.g. by banging head against it, does not prove stuck door. – Cheers and hth. - Alf Oct 10 '12 at 16:54
  • Feel free to propose feature tests but expect them to not be accepted based on the argument given. There is a second argument which would convince most committee members: feature trsts would encourage creations of systems accepting subsets. I realize that feature tests can be implemented and, e.g., clang has feature tests. Standardizing them is still pointless because the standard only has implications for conforming implementations which, by definition, implement all features. – Dietmar Kühl Oct 10 '12 at 17:08
  • huh, another fallacy. real compilers do add the features one by one. how many fallacies do those committee members throw about each day, then? [rhetorical question] yes i understand it's not you, and it's not even committee members in general. it's just so annoying that such lack of logic is permitted to rule in a highly technical decision making body. ok that the president of the us these days has to pretend to be religious. but for a language committee, oh, it hurts to hear that. – Cheers and hth. - Alf Oct 10 '12 at 18:04
1

clang has some built-in macros for various feature checks: clang feature-check macros Would be nice if all compiler vendors would pick up these (and more).

mitchnull
  • 6,161
  • 2
  • 31
  • 23
  • 1
    Would be even nicer if the compiler vendors implemented the real features, so the macros would not be needed. :-) – Bo Persson Oct 10 '12 at 16:15
0

“What I would like to have, is something like a set of macro which tells me what features are available on the compiler I am using.”

There's no such thing in the standard.

A practical approach to compiler differences is to have a header for each compiler and compiler version you support. These headers should have the same name. Which one is included depends on the include path, tool usage, which is easy to customize for each compiler.

I call that concept virtual headers. I've found that it works nicely for three levels: system dependency, compiler dependency and version dependency. I think the scheme doesn't scale up to more than that, but on the other hand, that seems to be all that one needs.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • @MatthieuM.: you may be right. i was thinking of the standard, but boost, if they really cover the relevant stuff, would be just as good. in practice. – Cheers and hth. - Alf Oct 10 '12 at 16:55
  • re Matthieu's comment, i fixed the answer to say what i intended, adding the "in the standard", so his comment may seem a little odd now – Cheers and hth. - Alf Oct 10 '12 at 18:06
  • Thanks for the notice. I would note that there is actually a little something in the Standard: the `__cplusplus` macro is meant to have a specific value for each version of the C++ Standard and a compiler should only advertise a Standard it fully implements. It's not so fine grained... – Matthieu M. Oct 11 '12 at 06:34