Macros math.h

The DOMAIN macro in math.h is confronted with enumerations and possibly other types. I don’t know what to do with it.

 #include <algorithm> enum Type { DOMAIN }; int main(){ Type t = Type::DOMAIN; return 0; } 

Compile with the -std = C ++ 11 flag. The version of this C99 code compiles fine:

 #include <algorithm> enum Type { DOMAIN }; int main(){ Type t = DOMAIN; return 0; } 

I checked the source code and the library is to blame. the algorithm includes stl_algo.h, which has an ifdef:

 #if __cplusplus >= 201103L #include <random> // for std::uniform_int_distribution #include <functional> // for std::bind #endif 

The following code compiles in the C ++ 11 compiler:

 #include <random> #include <iostream> int main(){ std::cout << DOMAIN << std::endl; return 0; } 

Is this a sign or a mistake?

EDIT * dirty fix:

 #ifdef DOMAIN #undef DOMAIN #endif 
+5
source share
2 answers

This is a mistake (or "wart" if you want to be generous).

The rest of this answer applies only to GCC and the standard Gnu library libraries. The man pages link to the linux system (but I added links to man7.org ).

The DOMAIN macro comes from the support of math.h System V. (See man matherr .) System V support is usually _SVID_SOURCE by defining the macro of the _SVID_SOURCE function (see man feature_test_macros ), but it is included with many other extensions if _GNU_SOURCE defined, or by default if function macros are not defined.

gcc predefines _GNU_SOURCE for C programs if the --std option --std omitted or set to gnu## . The various options --std=c## call the __STRICT_ANSI__ definition. Therefore, compiling C code with some explicit C standard will suppress System V extensions. This is necessary because System V extensions are not standards compliant, even Posix, as they pollute the global namespace. ( DOMAIN is just one example of this contamination.)

However, g++ defines _GNU_SOURCE even if --std=c++## is specified, and therefore the System V extension will expand. (Thanks to @dyp for linking to this libstdC ++ FAQ. And this is a long and unconvincing discussion on the mailing list since 2001 Gcc )

An ugly workaround is to configure the functions yourself, and then undefine __USE_SVID :

 #include <features.h> #undef __USE_SVID #include <random> #include <iostream> int main(){ std::cout << DOMAIN << std::endl; return 0; } 

( Live on coliru )

IMHO, this is not necessary. But there it is.

+6
source

§ 17.6.5.2 [res.on.headers] / 1 of N4140 says:

The C ++ header may contain other C ++ headers. The C ++ header should contain declarations and definitions, which are contained in its brief description. The C ++ header, shown in its brief description, including other C ++ headers, should provide declarations and definitions that appear in synonyms for these other headers.

Therefore, it is valid for <algorithm> to #include <cmath> , which introduces an offensive macro constant into your namespace.

Please note, however, that your “quick and dirty fix” is prohibited by the standard (§ 17.6.4.3.1 [macro.names] / 1):

A translation unit that includes a standard library header must not declare the names #define or #undef in any standard library header.

You need to choose a name other than DOMAIN for the enum constant.

0
source

All Articles