2

I asked a question here about assert which is implemented in the standard as a macro, not a function.

This had caused me an issue because the way that assert appears to be a function in the way it takes a parameter: assert(true) Thus I tried to use it as: std::assert(true) and of course being a macro that didn't work.

My question is this: Are there any other macros provided by the standard library which would appear as functions that take parameters?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 3
    You can find a copy of the standard [here](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf) - now start reading ;-) – Jesper Juhl Jun 05 '17 at 13:07
  • 3
    [`offsetof`](http://en.cppreference.com/w/cpp/types/offsetof) is one typical such function-like macro. Other function may be implemented as macros or as proper functions (though that's more true for C functions, since all C++ functions have to be in the `std` namespace). – Some programmer dude Jun 05 '17 at 13:08
  • Just in case You were wondering, `assert` is implemented as a function like macro because it can be turned off by defining `NDEBUG`. – riodoro1 Jun 05 '17 at 13:09
  • 1
    @riodoro1 you don't need something to be a macro to be able to turn it off that way.. – Jesper Juhl Jun 05 '17 at 13:11
  • @riodoro1 It didn't have to be implemented as a macro. `#ifdef NDEBUG void assert(const bool) {} #else void assert(const bool condition) { /*implementation defined*/ } #endif` would have worked just as well. I think it's just implemented as a macro cause that's how it was handled in C. – Jonathan Mee Jun 05 '17 at 13:13
  • 3
    @JesperJuhl True, but you *do* need it to be a macro to be able to print the expression failing the assertion. – Some programmer dude Jun 05 '17 at 13:13
  • 2
    You're going to have to look at C. [headers]/5 *Names which are defined as macros in C shall be defined as macros in the C++ standard library, even if C grants license for implementation as functions. [ Note: The names defined as macros in C include the following: assert, offsetof, setjmp, va_arg, va_end, and va_start. —end note ]* – NathanOliver Jun 05 '17 at 13:30
  • @NathanOliver Well that's pretty much the answer right there ain't it? I'd be happy accepting it. I've always been puzzled about why we're constantly warned against macros being bad practice and yet the standard is implemented with them. I guess this pretty much explains that. – Jonathan Mee Jun 05 '17 at 13:37

1 Answers1

5

If we look at [headers] paragraphs 5 and 6 we have

Names which are defined as macros in C shall be defined as macros in the C++ standard library, even if C grants license for implementation as functions. [ Note: The names defined as macros in C include the following: assert, offsetof, setjmp, va_arg, va_end, and va_start. —end note ]

Names that are defined as functions in C shall be defined as functions in the C++ standard library.

So, if it is defined as a macro in C, it will be a macro in C++. There are a couple of exceptions though. from [support.runtime] paragraphs 7 and 8

The header <cstdalign> and the header <stdalign.h> shall not define a macro named alignas.

The header <cstdbool> and the header <stdbool.h> shall not define macros named bool, true, or false.

Although that those exceptions are covered by [headers]/7 as well

Identifiers that are keywords or operators in C++ shall not be defined as macros in C++ standard library headers.

There is also an exception that all classification macros defined in 7.12.3 Classification macros be overloaded by functions per [c.math]/10

The classification/comparison functions behave the same as the C macros with the corresponding names defined in 7.12.3, Classification macros, and 7.12.14, Comparison macros in the C Standard. Each function is overloaded for the three floating-point types, as follows:

int fpclassify(float x);
bool isfinite(float x);
bool isinf(float x);
bool isnan(float x);
bool isnormal(float x);
bool signbit(float x);
bool isgreater(float x, float y);
bool isgreaterequal(float x, float y);
bool isless(float x, float y);
bool islessequal(float x, float y);
bool islessgreater(float x, float y);
bool isunordered(float x, float y);
int fpclassify(double x);
bool isfinite(double x);
bool isinf(double x);
bool isnan(double x);
bool isnormal(double x);
bool signbit(double x);
bool isgreater(double x, double y);
bool isgreaterequal(double x, double y);
bool isless(double x, double y);
bool islessequal(double x, double y);
bool islessgreater(double x, double y);
bool isunordered(double x, double y);
int fpclassify(long double x);
bool isfinite(long double x);
bool isinf(long double x);
bool isnan(long double x);
bool isnormal(long double x);
bool signbit(long double x);
bool isgreater(long double x, long double y);
bool isgreaterequal(long double x, long double y);
bool isless(long double x, long double y);
bool islessequal(long double x, long double y);
bool islessgreater(long double x, long double y);
bool isunordered(long double x, long double y);
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 1
    If I recall, there are a few function-style macros in `` that are actually functions in ``, like `isnan` and `isinf` for testing floating point values. I would hope a good implementation would give you the functions (rather than the macros) if you were to include `` into C++, but who knows? – Adrian McCarthy Jun 05 '17 at 16:53
  • @AdrianMcCarthy Oh snap you're right, in C they are macros: http://en.cppreference.com/w/c/numeric/math/isnan but in C++ they are functions: http://en.cppreference.com/w/cpp/numeric/math/isnan I wonder how the requirement Nathan Oliver cites is satisfied here? – Jonathan Mee Jun 05 '17 at 17:04
  • 1
    @AdrianMcCarthy Answer updated with why those are functions. – NathanOliver Jun 05 '17 at 17:19
  • @NathanOliver I'd upvote you again... but I can't... I'll accept sometime tomorrow instead. – Jonathan Mee Jun 05 '17 at 17:27
  • @JonathanMee No problem and don't fell obligated. Glad to help. – NathanOliver Jun 05 '17 at 17:28