How to compare two preprocessor macros with the same name? - c++

I have a project where there are two different preprocessor macros with the same name, defined in two different include files (from two different libraries), and I have to check if they have the same value at build time.
So far I could make this check at run time, assigning the macro values to different variables in different implementation files, each including only one of the headers involved.
How can I do it at build time?
This is what I tried so far (where Macro1.h and Macro2.h are third-party files I cannot modify):
Header files:
TestMultiMacros.h:
#ifndef TEST_MULTI_MACROS_H
#define TEST_MULTI_MACROS_H
struct Values
{
static const unsigned int val1, val2;
static const unsigned int c1 = 123, c2 = 123;
};
#endif // TEST_MULTI_MACROS_H
Macro1.h:
#ifndef MACRO1_H
#define MACRO1_H
#define MY_MACRO 123
#endif // MACRO1_H
Macro2.h:
#ifndef MACRO2_H
#define MACRO2_H
#define MY_MACRO 123
#endif // MACRO2_H
Implementation files:
TestMultiMacros1.cpp:
#include "TestMultiMacros.h"
#include "Macro1.h"
const unsigned int Values::val1 = MY_MACRO;
TestMultiMacros2.cpp:
#include "TestMultiMacros.h"
#include "Macro2.h"
const unsigned int Values::val2 = MY_MACRO;
entrypoint.cpp:
#include "TestMultiMacros.h"
using namespace std;
static_assert(Values::val1 == Values::val2, "OK"); // error: expression did not evaluate to a constant
static_assert(Values::c1 == Values::c2, "OK");
int main()
{
}
I would be interested in a solution using both C++11 and C++17.

Include the first header. Then save the value of the macro to a constexpr variable:
constexpr auto foo = MY_MACRO;
Then include the second header. It should silently override MY_MACRO. If your compiler starts complaining, do #undef MY_MACRO first.
Then compare the new value of the macro with the variable using a static_assert:
static_assert(foo == MY_MACRO, "whatever");

Here's a very simple C++17 test which works with arbitrary (non-function) macros by comparing the text of the macro expansion. For c++11, which lacks the constexpr comparison in std::string_view, you can write it yourself in a couple of lines, as shown in this answer.
#include <string_view>
#define STRINGIFY(x) STRINGIFY_(x)
#define STRINGIFY_(x) #x
#include "macro1.h"
//#define MY_MACRO A night to remember
constexpr const char* a = STRINGIFY(MY_MACRO);
#undef MY_MACRO
#include "macro2.h"
//#define MY_MACRO A knight to remember
constexpr const char* b = STRINGIFY(MY_MACRO);
static_assert(std::string_view(a) == b, "Macros differ");
int main() { }
(Godbolt: https://godbolt.org/z/nH5qVo)
Of course, this depends on what exactly you mean by equality of macros. This version will report failure if one header file has
#define MY_MACRO (2+2)
and the other has
#define MY_MACRO 4
Also worth noting that stringification normalises whitespace but it does not normalise the presence of whitespace other than trimming the ends. So (2 + 2) and (2 + 2) will compare as equal, but not (2+2) and ( 2 + 2 )

Related

Get a different value with macro every time it's used [duplicate]

I'm writing a bunch of related preprocessor macros, one of which generates labels which the other one jumps to. I use them in this fashion:
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL();
MAKE_LABEL();
)
I need some way to generate unique labels, one for each inner MAKE_LABEL call, with the preprocessor. I've tried using __LINE__, but since I call MAKE_LABEL inside another macro, they all have the same line and the labels collide.
What I'd like this to expand to is something like:
MAKE_FUNNY_JUMPING_LOOP(
my_cool_label_1: // from first inner macro
...
my_cool_label_2: // from second inner macro
...
)
Is there a way to generate hashes or auto-incrementing integers with the preprocessor?
If you're using GCC or MSVC, there is __COUNTER__.
Other than that, you could do something vomit-worthy, like:
#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
I use this:
#define MERGE_(a,b) a##b
#define LABEL_(a) MERGE_(unique_name_, a)
#define UNIQUE_NAME LABEL_(__LINE__)
int main()
{
int UNIQUE_NAME = 1;
return 0;
}
... and get the following:
int main()
{
int unique_name_8 = 1;
return 0;
}
As others noted, __COUNTER__ is the easy but nonstandard way of doing this.
If you need extra portability, or for other cool preprocessor tricks, the Boost Preprocessor library (which works for C as well as C++) will work. For example, the following header file will output a unique label wherever it's included.
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/slot/slot.hpp>
#if !defined(UNIQUE_LABEL)
#define UNIQUE_LABEL
#define BOOST_PP_VALUE 1
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#else
#define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1))
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#endif
BOOST_PP_CAT(my_cool_label_, BOOST_PP_SLOT(1)):
Sample:
int main(int argc, char *argv[]) {
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
return 0;
}
preprocesses to
int main(int argc, char *argv[]) {
my_cool_label_1:
printf("%x\n", 1234);
my_cool_label_2:
printf("%x\n", 1234);
my_cool_label_3:
return 0;
}
I can't think of a way to automatically generate them but you could pass a parameter to MAKE_LABEL:
#define MAKE_LABEL(n) my_cool_label_##n:
Then...
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL(0);
MAKE_LABEL(1);
)
You could do this:
#define MAKE_LABEL() \
do { \
my_cool_label: \
/* some stuff */; \
goto my_cool_label; \
/* other stuff */; \
} while (0)
This keeps the scope of the label local, allowing any number of them inside the primary macro.
If you want the labels to be accessed more globally, it's not clear how your macro "MAKE_FUNNY_JUMPING_LOOP" references these labels. Can you explain?
It doesn't seem possible with a standard preprocessor, although you could fake it out by putting parameters within MAKE_LABEL or MAKE_FUNNY_JUMPING_LOOP, and use token pasting to create the label.
There's nothing preventing you from making your own preprocessing script that does the automatic increment for you. However, it won't be a standard C/C++ file in that case.
A list of commands available: http://www.cppreference.com/wiki/preprocessor/start

Can BOOST_PP_DEFINED be implemented?

Is it possible to write a function-like C preprocessor macro that returns 1 if its argument is defined, and 0 otherwise? Lets call it BOOST_PP_DEFINED by analogy with the other boost preprocessor macros, which we can assume are also in play:
#define BOOST_PP_DEFINED(VAR) ???
#define XXX
BOOST_PP_DEFINED(XXX) // expands to 1
#undef XXX
BOOST_PP_DEFINED(XXX) // expands to 0
I'm expecting to use the result of BOOST_PP_DEFINED with BOOST_PP_IIF:
#define MAGIC(ARG) BOOST_PP_IIF(BOOST_PP_DEFINED(ARG), CHOICE1, CHOICE2)
In other words, I want the expansion of MAGIC(ARG) to vary based on whether ARG is defined or not at the time that MAGIC is expanded:
#define FOO
MAGIC(FOO) // expands to CHOICE1 (or the expansion of CHOICE1)
#undef FOO
MAGIC(FOO) // expands to CHOICE2 (or the expansion of CHOICE2)
I also found it interesting (and somewhat surprising) that the following doesn't work:
#define MAGIC(ARG) BOOST_PP_IIF(defined(arg), CHOICE1, CHOICE2)
Because apparently defined is only valid in the preprocessor when used as part of an #if expression.
I somewhat suspect that the fact that boost preprocessor doesn't already offer BOOST_PP_DEFINED is evidence for its impossibility, but it can't hurt to ask. Or, am I missing something really obvious about how to achieve this.
EDIT: To add some motivation, here is why I want this. The traditional way to do "API" macros to control import/export is to declare a new set of macros for every library, which means a new header, etc. So if we have class Base in libbase and class Derived in libderived, then we have something like the following:
// base_config.hpp
#if LIBBASE_COMPILING
#define LIBBASE_API __declspec(dllexport)
#else
#define LIBBASE_API __declspec(dllimport)
// base.hpp
#include "base_config.hpp"
class LIBBASE_API base {
public:
base();
};
// base.cpp
#include "base.hpp"
base::base() = default;
// derived_config.hpp
#if LIBDERIVED_COMPILING
#define LIBDERIVED_API __declspec(dllexport)
#else
#define LIBDERIVED_API __declspec(dllimport)
// derived.hpp
#include "derived_config.hpp"
#include "base.hpp"
class LIBDERIVED_API derived : public base {
public:
derived();
};
// derived.cpp
#include "derived.hpp"
derived::derived() = default;
Now, obviously, each of the _config.hpp header would really be a lot more complex, defining several macros. We could probably pull out some of the commonalities into a generic config_support.hpp file, but not all. So, in an effort to simplify this mess, I wondered if it would be possible make this generic, so that one set of macros could be used, but that would expand differently based on which _COMPILING macros were in play:
// config.hpp
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)
#define API_IMPL2(COND) BOOST_PP_IIF(COND, EXPORT, IMPORT)()
#define API_IMPL(ARG) API_IMPL2(BOOST_PP_DEFINED(ARG))
#define API(LIB) API_IMPL(LIB ## _COMPILING)
// base.hpp
#include "config.hpp"
class API(LIBBASE) base {
public:
base();
};
// base.cpp
#include "base.hpp"
base::base() = default;
// derived.hpp
#include "config.hpp"
#include "base.hpp"
class API(LIBDERIVED) derived : public base {
public:
derived();
};
// derived.cpp
#include "derived.hpp"
derived::derived() = default;
In other words, when compiling base.cpp, API(LIBBASE) would expand to __declspec(dllexport) because LIBBASE_COMPILING was defined on the command line, but when compiling derived.cpp API(LIBBASE) would expand to __declspec(dllimport) because LIBBASE_COMPILING was not defined on the command line, but API(LIBDERIVED) would now expand to __declspec(dllexport) since LIBDERIVED_COMPILING would be. But for this to work it is critical that the API macro expand contextually.
It looks like you could use BOOST_VMD_IS_EMPTY to implement the required behavior. This macro returns 1 if its input is empty or 0 if its input is not empty.
Trick based on the observation that when XXX is defined by #define XXX, empty parameter list passed to BOOST_VMD_IS_EMPTY(XXX) during expansion.
Sample implementation of MAGIC macro:
#ifndef BOOST_PP_VARIADICS
#define BOOST_PP_VARIADICS
#endif
#include <boost/vmd/is_empty.hpp>
#include <boost/preprocessor/control/iif.hpp>
#define MAGIC(XXX) BOOST_PP_IIF(BOOST_VMD_IS_EMPTY(XXX), 3, 4)
#define XXX
int x = MAGIC(XXX);
#undef XXX
int p = MAGIC(XXX);
For Boost 1.62 and VS2015 preprocessor output will be:
int x = 3;
int p = 4;
This approach has a number of flaws, e.g. it's not working if XXX defined with #define XXX 1. BOOST_VMD_IS_EMPTY itself has limitations.
EDIT:
Here is the implementation of the required API macros based on BOOST_VMD_IS_EMPTY:
// config.hpp
#ifndef BOOST_PP_VARIADICS
#define BOOST_PP_VARIADICS
#endif
#include <boost/vmd/is_empty.hpp>
#include <boost/preprocessor/control/iif.hpp>
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)
#define API_IMPL2(COND) BOOST_PP_IIF(COND, EXPORT, IMPORT)
#define API_IMPL(ARG) API_IMPL2(BOOST_VMD_IS_EMPTY(ARG))
#define API(LIB) API_IMPL(LIB ## _COMPILING)
Let's see what preprocessor will output for:
// base.hpp
#include "config.hpp"
class API(LIBBASE) base {
public:
base();
};
When LIBBASE_COMPILING defined, GCC output:
class __attribute__((dllexport)) Base
{
public:
Base();
};
When LIBBASE_COMPILING is not defined, GCC output:
class __attribute__((dllimport)) Base
{
public:
Base();
};
Tested with VS2015 and GCC 5.4 (Cygwin)
EDIT 2:
As #acm mentioned when parameter defined with -DFOO it's same as -DFOO=1 or #define FOO 1. In this case approach based on BOOST_VMD_IS_EMPTY is not working. To overcome it you can use BOOST_VMD_IS_NUMBER (thnx to #jv_ for the idea). Implementation:
#ifndef BOOST_PP_VARIADICS
#define BOOST_PP_VARIADICS
#endif
#include <boost/vmd/is_number.hpp>
#include <boost/preprocessor/control/iif.hpp>
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)
#define API_IMPL2(COND) BOOST_PP_IIF(COND, EXPORT, IMPORT)
#define API_IMPL(ARG) API_IMPL2(BOOST_VMD_IS_NUMBER(ARG))
#define API(LIB) API_IMPL(LIB ## _COMPILING)
It's not a pure is defined check, but we can get all the way to checking for a particular token name.
Annotating a first principles solution based on Cloak from Paul Fultz II:
First provide the ability to conditionally choose text based on macro expansion to 0 or 1
#define IIF(bit) PRIMITIVE_CAT(IIF_, bit)
#define IIF_0(t, f) f
#define IIF_1(t, f) t
Basic concatenation
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
Logical operators (compliment and and)
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y
A method to see whether a token is or is not parens "()"
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0, )
#define PROBE(x) x, 1,
#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x)
#define IS_PAREN_PROBE(...) PROBE(~)
Note IS_PAREN works because "IS_PAREN_PROBE X" turns in to one arg in CHECK(), where as "IS_PAREN_PROBE ()" turns into PROBE(~) which turns into ~, 1. At which point we can pick up the 1 from CHECK
Another utility to eat some macro arguments as needed
#define EAT(...)
Here, we take advantage of blue painting (the thing which prevents naively recursive macros) to check whether or not two tokens are the same. If they are this collapses to (). Otherwise not, which we can detect via IS_PAREN.
This relies on COMPARE_XXX identity macros existing for any given symbol
#define PRIMITIVE_COMPARE(x, y) IS_PAREN(COMPARE_##x(COMPARE_##y)(()))
We add an IS_COMPARABLE trait for that helper
#define IS_COMPARABLE(x) IS_PAREN(CAT(COMPARE_, x)(()))
We work backwards to EQUAL by checking if both args are comparable, then converting to primitive_compare if they are. If not, we're not equal and eat the following args.
#define NOT_EQUAL(x, y) \
IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y))) \
(PRIMITIVE_COMPARE, 1 EAT)(x, y)
EQUAL is the compliment
#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y))
And finally, the macro we actually want.
First we enable compare for "BUILDING_LIB"
#define COMPARE_BUILDING_LIB(x) x
Then our actual deciding macro, which is an integer if on whether a symbol resolves to "BUILDING_LIB"
#define YES_IF_BUILDING_LIB(name) IIF(EQUAL(name, BUILDING_LIB))("yes", "no")
#include <iostream>
#define FOO BUILDING_LIB
int main(int, char**) {
std::cout << YES_IF_BUILDING_LIB(FOO) << "\n";
std::cout << YES_IF_BUILDING_LIB(BAR) << "\n";
}
Which outputs:
yes
no
See his great blogpost (that I cribbed from): C Preprocessor tricks, tips, and idioms
Since you intend to use FOO as file-level switch that you control, I suggest that you use a simpler solution. The suggested solution is easier to read, less surprising, requires no dirty magic.
Instead of #define MAGIC(ARG) BOOST_PP_IIF(BOOST_PP_DEFINED(ARG), CHOICE1, CHOICE2) you simply -D with MAGIC=CHOICE1 or MAGIC=CHOICE2 per file.
You don't have to do it for all files. The compiler will tell you when you used MAGIC in a file, but did not make a choice.
If CHOICE1 or CHOICE2 is a major default you don't wish to specify, you can use -D to set default for all files and -U + -D to change your decision per file.
If CHOICE1 or CHOICE2 is lengthy, you can #define CHOICE1_TAG actual_contents in your header file where you originally intended to define MAGIC and then -D with MAGIC=CHOICE1_TAG, because CHOICE1_TAG will be automatically expanded into actual_contents.

#define 'ing multiple macros in one line

In C++, we can use #define to define a macro like #define PI 3.14 and then use PI all throughout the code to represent 3.14.
My question is : Can we #define multiple macros in one line so that I don't need to write n lines to define n macros.
I actually want to do this to represent array elements by alternate names (letters actually) as evident by the code snippet below.
#include <cstdlib>
#include <math.h>
#include <time.h>
#define R dig[0]
#define E dig[1]
#define D dig[2]
#define B dig[3]
#define L dig[4]
#define U dig[5]
#define Y dig[6]
#define O dig[7]
#define W dig[8]
using namespace std;
int main() {
int dig[9]={1,2,3,4,5,6,7,8,9}; // R,E,D,B,L,U,Y,O,W
return 0;
}
Is there a method to #define all those macros in one line so that I don't have to write multiple lines like in the above code snippet? Thanks.
Defining one macro is bad enough.
In your comments, you wonder about an alternative method. There is one in C++ :
auto &R = dig[0], &E = dig[1], &D = dig[2] // etc ...
This isn't just one line but even one statement. Slightly more verbose, you could do
auto &R = dig[0]; auto &E = dig[1]; auto &D = dig[2] // etc ...
and it's now multiple statements on one line. (see the semicolons?)
AFAIK the end of #define statement is the end of the line. So no, you can't write a few separate ones in one line. As someone mentioned, use enum here instead.
No, this is not possible in either C or C++.
Have you considered writing a program to generate repetitive code at build time? That's an under-appreciated technique.

Save original value of C++ preprocessor macro

I want to save the original textual value of a macro so that I can then redefine the macro and still refer to the original value. My use case involves a macro to a macro, so that the value I am trying to save is still itself a macro. I have a small example of attempts in an online interpreter, which I am copying the code from here. I am aware that other SO questions discuss similar ideas but I have not found anything that covers my use case.
#include <stdio.h>
#define STR(X) (#X)
#define GLOBAL_INT (3)
// I AM TRYING TO SAVE THE TEXTUAL MACRO CONTENT "GLOBAL_INT" (WITHOUT THE QUOTES)
// IN ANOTHER MACRO SO THAT I CAN UNDEFINE GIM AND STILL REFER TO GLOBAL_INT
#define GIM (GLOBAL_INT)
#define GIM_SAVE (GIM)
#define GIM_SAVE_STR (STR(GIM))
#define STR_GIM_SAVE (STR(GIM_SAVE))
const char *strGimSave = STR(GIM_SAVE);
const char *gimSaveStr = GIM_SAVE_STR;
const char *strGimSaveM = STR_GIM_SAVE;
const char *gimStr = STR(GIM);
#undef GIM
int main(int argc, char *argv[])
{
printf("strGimSave=%s\n", strGimSave);
printf("gimSaveStr=%s\n", gimSaveStr);
printf("strGimSaveM=%s\n", strGimSaveM);
printf("gimStr=%s\n", gimStr);
const char *gim_save = STR(GIM_SAVE);
const char *gim_save_str = GIM_SAVE_STR;
const char *str_gim_save = STR_GIM_SAVE;
printf("\ngim_save=%s\n", gim_save);
printf("gim_save_str=%s\n", gim_save_str);
printf("str_gim_save=%s\n", str_gim_save);
return 0;
}
Same code in online interpreter
Edit: I am trying to output "GLOBAL_INT" in the above code. The above code outputs:
strGimSave=GIM_SAVE
gimSaveStr=GIM
strGimSaveM=GIM_SAVE
gimStr=GIM
gim_save=GIM_SAVE
gim_save_str=GIM
str_gim_save=GIM_SAVE
It is not possible. C/C++ preprocessor expands macros on evaluation only. There is no way to tell it to define macro to expanded result of another.
That said, the first part of your sample would actually do what you want if you used correct definition of STR:
#include <stdio.h>
// HERE, extra level of indirection
#define STR2(X) (#X)
#define STR(X) STR2(X)
#define GLOBAL_INT (3)
#define GIM (GLOBAL_INT)
#define GIM_SAVE (GIM)
#define GIM_SAVE_STR (STR(GIM))
#define STR_GIM_SAVE (STR(GIM_SAVE))
const char *strGimSave = STR(GIM_SAVE);
const char *gimSaveStr = GIM_SAVE_STR;
const char *strGimSaveM = STR_GIM_SAVE;
const char *gimStr = STR(GIM);
#undef GIM
int main(int argc, char *argv[])
{
printf("strGimSave=%s\n", strGimSave);
printf("gimSaveStr=%s\n", gimSaveStr);
printf("strGimSaveM=%s\n", strGimSaveM);
printf("gimStr=%s\n", gimStr);
const char *gim_save = STR(GIM_SAVE);
const char *gim_save_str = GIM_SAVE_STR;
const char *str_gim_save = STR_GIM_SAVE;
printf("\ngim_save=%s\n", gim_save);
printf("gim_save_str=%s\n", gim_save_str);
printf("str_gim_save=%s\n", str_gim_save);
return 0;
}
Now produces
strGimSave=(((3)))
gimSaveStr=((3))
strGimSaveM=(((3)))
gimStr=((3))
gim_save=(GIM)
gim_save_str=GIM
str_gim_save=(GIM)
(See live on coliru)
As you see once you #undef GIM the macros stop expanding to "3", but the string constants created while GIM was defined retain the value. With all the parenthesis that you've put into those macros.
When applying preprocessor operators to macro argumments, you should add an extra level of indirection (Another macro) just to expand the macro argumments properly. Consider this example using the token concatenation operator (##):
#define TOKEN_CAT_IMPL(x,y) x##x
#define TOKEN_CAT(x,y) TOKEN_CAT_IMPL(x,y) // <--- Here x and y are expanded before passed
Now you could use it for whatever you like:
#define FOO_IDENTIFIER( id ) TOKEN_CAT( foo_ , id );
#define ID hello
int FOO_IDENTIFIER( ID ) = 0; // int foo_hello = 0;
Here is a running example.
EDIT:
Here is your code working by applying the solution explained here. Note how the second outputs are GIM, since that macro was undefined and GIM was treated as a token only.

How to count number of macro execution?

I have two macros that declares class properties:
DECLARE_QUERY_PARAM_LONG(name)
DECLARE_QUERY_PARAM_STRING(name)
I want to count number of calls of this macros inside of my class and init
static const size_t paramsCount
with that number like this:
class MyClass {
...
DECLARE_QUERY_PARAM_LONG(param1)
DECLARE_QUERY_PARAM_STRING(param2)
DECLARE_QUERY_PARAM_STRING(param3)
DECLARE_QUERY_PARAM_LONG(param4)
static const size_t paramsCount = PARAMS_COUNT; // 4 in this case
...
};
Is this ever possible?
There would be a solution, rather complicated:
All your parameters will have a fixed name (say param)
You need to create one header file per type
You shall need boost
So here is the header creation file:
// file declare_int.h
#include BOOST_PP_UPDATE_COUNTER()
int stringize(param,BOOST_PP_COUNTER) ;
and the class file:
//file declare_auto.cpp
#include <boost/preprocessor/slot/counter.hpp>
#define _stringize(a,b) a##b
#define stringize(a,b) _stringize(a,b)
// reset counter
#if defined(BOOST_PP_COUNTER)
#undef BOOST_PP_COUNTER
#endif
class A {
public:
#include "declare_int.h"
#include "declare_int.h"
#include "declare_int.h"
#include "declare_int.h"
static const int nbParams = BOOST_PP_COUNTER ;
};
and finally the output of:
g++ -E -P -c declare_auto.cpp -IPATH_TO_BOOST
is
class A {
public:
int param1 ;
int param2 ;
int param3 ;
int param4 ;
static const int nbParams = 4 ;
};
You can at least count number of lines in the following way:
class MyClass
{
static const int line_1 = __LINE__;
DECLARE_QUERY_PARAM_LONG(param1)
DECLARE_QUERY_PARAM_STRING(param2)
DECLARE_QUERY_PARAM_STRING(param3)
DECLARE_QUERY_PARAM_LONG(param4)
static const int line_2 = __LINE__;
static const int macro_calls = line_2 - line_1 - 1;
public:
MyClass()
{
cout << macro_calls << endl;
}
};
But I think you'll need C++11 to do that. And You cannot have empty lines within those two __LINE__s. Otherwise, you'll have to count those empty lines as well.
As such no.
What you are asking for would require some form of introspection, which is not natively supported by C++.
You can improve the macro though, if you had:
DECLARE_QUERY_PARAMS(((LONG , param1))
((STRING, param2))
((STRING, param3))
((LONG , param4)))
then you could do what you want.
You can have a look at Boost.Preprocessor to learn how to obfuscate your sources this way.
Note: this uses a Sequence, in boost parlance.
I don't think there's a standard way to do this, but the DevStudio compiler has this preprocessor macro:
__COUNTER__
Expands to an integer starting with 0 and incrementing by 1 every time it is used in a compiland. __COUNTER__ remembers its state when using precompiled headers. If the last __COUNTER__ value was 4 after building a precompiled header (PCH), it will start with 5 on each PCH use.
__COUNTER__ lets you generate unique variable names. You can use token pasting with a prefix to make a unique name. For example:
// pre_mac_counter.cpp
#include <stdio.h>
#define FUNC2(x,y) x##y
#define FUNC1(x,y) FUNC2(x,y)
#define FUNC(x) FUNC1(x,__COUNTER__)
int FUNC(my_unique_prefix);
int FUNC(my_unique_prefix);
No. Macro's don't respect scope at all, and don't understand that they're inside a class.
No. Macros aren't executed, they're expanded and not even by compiler, but by preprocessor.