Macro to Replace C++ Operator New

C++ macro to replace .at() with []

In general I'd avoid this kind of macros, as they are "invisible" (so the altered semantics is subtly hidden from anyone not in the knows) and can alter functionality of code that actually expected at to throw on out of bounds, even in release builds. If anything, I'd define something that stands out, for example an all-uppercase AT.

Fortunately, this is not actually needed, as the "big three" C++ runtimes already have builtin functionality to conditionally enable boundary checking on operator[] (which has also the advantage of being more readable than at):

  • if you are using g++/libstdc++ if you pass -​D_GLIBCXX_DEBUG you get the debug version of STL containers, which perform boundary checks on operator[], plus a lot of other debug checks on iterators;
  • CLang/libc++ can do similar checks setting _LIBCPP_DEBUG to 1;
  • for Visual C++ the analogous functionality is enabled with ITERATOR_DEBUG_LEVEL set to 2 (and it's already enabled by default in debug builds).

Incidentally, some of these errors (those that actually overflow the allocated size, not just the "logically valid" size of the vector) may also be spotted using the address sanitizer (-fsanitize=address on gcc and clang) or valgrind (slow!) and similar tools.

Doing conditional replacement using c++ macro?

This is the answer that answers the macro part and I would advise to provide operators overloads if possible and not to use macros in C++.

So first create your own small overloaded foreach macro that will apply a function on each argument:

#define M_FOREACH_1(func,_1) \
func(_1)
#define M_FOREACH_2(func,_1,_2) \
M_FOREACH_1(func,_1)func(_2)
#define M_FOREACH_3(func,_1,_2,_3) \
M_FOREACH_2(func,_1,_2)func(_3)
/// etc.
#define M_FOREACH_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) \
M_FOREACH_##N
#define M_FOREACH(func, ...) \
M_FOREACH_N(__VA_ARGS__,9,8,7,6,5,4,3,2,1)(func, __VA_ARGS__)

Then let's abstract it for some argument braced list that needs to be escaped, for verbosity:

#define M_FOREACHLIST_ESCAPE(...)  \
__VA_ARGS__
#define M_FOREACHLIST_IN(func, ...) \
M_FOREACH(func, __VA_ARGS__)
#define M_FOREACHLIST(func, list) \
M_FOREACHLIST_IN(func, M_FOREACHLIST_ESCAPE list)
// now we can
// M_FOREACHLIST(some_macro, (x, y, z))

After that it's typicall to define a function for expansion, apply it foreach some arguments list:

#define list() (x, y, z)

#define add(arg) res = res + arg;
M_FOREACHLIST(add, list())
// generates res = res + x;res = res + y;res = res + z;
#undef add

#define sub(arg) res = res - arg;
M_FOREACHLIST(sub, list())
// generates res = res - x;res = res - y;res = res - z;
#undef sub

// etc.

and I'm finding a way to not to write ... three times!

Pass member pointer to the function...

float generic_in_middle(point a, point b, point c, float d, float point::* mp){
if (b.*mp < a.*mp && a.*mp < c.*mp){
if (d > 0) return a.*mp;
if (d < 0) return a.*mp * a.*mp;
if (d == 0) return 0;
}
// TODO: add code here so that function returns something
}
float x_in_middle(point a, point b, point c, float d) {
return generic_in_middle(a, b, c, d, &point::x);
}
// etc.

How to properly replace global new & delete operators

That's not how this works. You replace the two operators, and this is done at link time. All you need to do is write a single TU that defines these operators and link it into the mix. Nobody else ever needs to know about this:

// optional_ops.cpp

void * operator new(std::size_t n) throw(std::bad_alloc)
{
//...
}
void operator delete(void * p) throw()
{
//...
}

In principle, there's no need for any header files to declare these functions (operator new, operator delete), since the declarations of those two functions are already hardcoded into the language, if you will. However, the names std, std::bad_alloc and std::size_t are not predeclared, so you will probably want to include <new> or some other header to provide those names.

In C++11 and beyond, you can alternatively use decltype(sizeof(0)) to get the size of the first parameter in a way that doesn't require any kind of library. C++11 also has a simpler exception model without dynamic exception specifications (which were finally removed from the language entirely in C++17).

void * operator new(decltype(sizeof(0)) n) noexcept(false)
{
//...
}

Replacement and stringification of #define

With

#define concatenate(a,b) a##b
#define same1(a) #a
#define same2(a) same1(a)

when you have same2(concatenate(1,2)), the argument of same2 is expanded before passing it to same1, so there, concatenate(1,2) is replaced by its result, 12 that then is stringified by same1 to produce "12".

With same1, no expansion of the macro argument occurs, since it's preceded by the stringification token #:

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

(section 6.10.3.1 (1) in n1570)

Defining a Macro in C with a set of operators

Macros do only textual substituation, so your code is actually equivalent to this:

int isOperator (char c) {
if (c != {'+', '-','*', '/', '%', '^'})
return 0;

return 1;
}

which is invalid C code, you cannot compare a char to an array of chars which doesn't make sense anyway.

You want this:

#include <stdio.h>
#include <stdlib.h>

int isOperator(char c) {
static char operators[] = { '+', '-','*', '/', '%', '^' };
for (int i = 0; i < sizeof operators; i++)
if (c == operators[i])
return 1;

return 0;
}

int main() {
printf("%d\n", isOperator('+'));
printf("%d\n", isOperator('j'));
return 0;
}

Or even shorter:

...
#include <string.h>
...
int isOperator(char c) {
char operators[] = "+-*/%^";
return strchr(operators, c) != NULL;
}

Parameterized macros involving the ## operator in the replacement-list

When the preprocessor detects a function-like macro invocation while scanning a source line, it completely expands the macro's arguments before substituting them into the macro's replacement text, except that where an argument appears as an operand of the stringification (#) or token-pasting (##) operator, its literal value is used for the operation. The resulting replacement text, with expanded arguments and the results of any # and ## operations substituted, is then rescanned for additional macros to expand.

Thus, with ...

CONCAT(a, CONCAT(b,c))

... the literal values of both arguments are used as operands for the token-pasting operation. The result is ...

aCONCAT(b,c)

. That is rescanned for further macros to expand, but aCONCAT is not defined as a macro name, so no further macro expansion occurs.

Now consider ...

CONCAT2(a, CONCAT2(b,c))

. In CONCAT2, neither argument is an operand of # or ##, so both are fully macro-expanded before being substituted. Of course a is unchanged, but CONCAT2(b,c) expands to CONCAT(b,c), which upon rescan is expanded to bc. By substitution of the expanded argument values into its replacement text, the outer CONCAT2 invocation expands to ...

CONCAT(a, bc)

. That expansion is then rescanned, in the context of the surrounding source text, for further macro expansion, yielding ...

abc

. That is again rescanned, but there are no further macro expansions to perform, so that's the final result.

Macro redefining logical operators

Alternate names for this and other operators are already part of standard C. Using #include <iso646.h> defines:























































NameReplacement
and&&
and_eq&=
bitand&
bitor|
compl~
not!
not_eq!=
or||
or_eq|=
xor^
xor_eq^=

How do I replace this preprocessor macro with a #include?

This cries out for a template.

class Example<class T>
{
...class definition...
};

The direct answer to the last part of your question - "given that I'm not in a macro definition any more, how do I get pasting and stringizing operators to work" - is "You can't". Those operators only work in macros, so you'd have to write macro invocations in order to get them to work.

Added:

@mackenir said "templates are not an option". Why are templates not an option? The code is simulating templates the old-fashioned pre-standard, pre-template way, and does so causing much pain and grief. Using templates would avoid that pain -- though there'd be a conversion operation.

@mackenir asked "is there a way to make things work with macros?" Yes, you can, but you should use templates - they are more reliable and maintainable. To make it work with macros, then you'd have to have the function names in the code in the included header be macro invocations.
You need to go through a level of indirection to get this to work correctly:

#define PASTE_NAME(x, y) PASTE_TOKENS(x, y)
#define PASTE_TOKENS(x, y) x ## y

#define TYPE_NAME Example
int PASTE_NAME(TYPE_NAME, _function_suffix)(void) { ... }

This level of indirection is an often necessary idiom for both tokenizing and stringizing operators.


Additional comments from @mackenir indicate continued problems. Let's make it concrete.

At the moment I am using a macro to define a bunch of fields and methods on various classes, like this:

class Example
{
// Use FIELDS_AND_METHODS macro to define some methods and fields
FIELDS_AND_METHODS(Example)
};

FIELDS_AND_METHODS is a multi-line macro that uses stringizing and token-pasting operators.

I would like to replace this with the following kind of thing

class Example
{
// Include FieldsNMethods.h, with TYPE_NAME preprocessor symbol
// defined, to achieve the same result as the macro.
#define TYPE_NAME Example
#include "FieldsNMethods.h"
};

OK. To make this concrete, we need a FIELDS_AND_METHODS(type) macro that is multi-line and uses token-pasting (I'm not going to deal with stringizing - the same basic mechanisms will apply, though).

#define FIELDS_AND_METHODS(type) \
type *next; \
type() : next(0) { } \
type * type ## _next() { return next; }

With luck, this declares a member of the type 'pointer to argument type', a constructor for that type, and a method (Example_next in this case) that returns that pointer.

So, this might be the macro - and we need to replace it such that the '#include' does the equivalent job.

The content of fieldsNmethods.h becomes:

#ifndef TYPE_NAME
#error TYPE_NAME not defined
#endif
#define FNM_PASTE_NAME(x, y) FNM_PASTE_TOKENS(x, y)
#define FNM_PASTE_TOKENS(x, y) x ## y

TYPE_NAME *next;
TYPE_NAME() : next(0) { }
TYPE_NAME * FNM_PASTE_NAME(TYPE_NAME, _next)() { return next; }

#undef FNM_PASTE_NAME
#undef FNM_PASTE_TOKENS

Note that the header would not contain multiple-inclusion guards; its raison d'etre is to allow it to be included multiple times. It also undefines its helper macros to permit multiple inclusion (well, since the redefinitions would be identical, they're 'benign' and wouldn't cause an error), and I prefixed them with FNM_ as a primitive namespace control on the macros. This generates the code I'd expect from the C pre-processor. and G++ doesn't witter but produces an empty object file (because the types declared are not used in my example code).

Note that this does not require any changes to the calling code except the one outlined in the question. I think the question should be improved using the SPOT "Single Point of Truth" principle (or DRY "Don't Repeat Yourself"):

#define TYPE_NAME Example
class TYPE_NAME
{
// Include FieldsNMethods.h, with TYPE_NAME preprocessor symbol
// defined, to achieve the same result as the macro.
#include "FieldsNMethods.h"
};


Related Topics



Leave a reply



Submit