Is it possible, using the C/C++ preprocessor, to count lines within a source file, into either a macro or some kind compile-time-available value? E.g. can I replace MAGIC1
, MAGIC2
and MAGIC3
in the following, and get the value 4 somehow when using MAGIC3
?
MAGIC1 // can be placed wherever you like before the relevant
// lines - either right before them, or in global scope etc.
foo(); MAGIC2
bar(); MAGIC2
baz(); MAGIC2
quux(); MAGIC2
// ... possibly a bunch of code here; not guaranteed to be in same scope ...
MAGIC3
Notes:
There is the __LINE__
preprocessor macro which gives you an integer for the line is appeared on. You could take its value on some line, and then some later line, and compare.
static const int BEFORE = __LINE__;
foo();
bar();
baz();
quux();
static const int AFTER = __LINE__;
static const int COUNT = AFTER - BEFORE - 1; // 4
If you want to count the occurrences of something rather than source lines, __COUNTER__
might be a non-standard option, supported by some compilers such as GCC and MSVC.
#define MAGIC2_2(c)
#define MAGIC2(c) MAGIC2_2(c)
static const int BEFORE = __COUNTER__;
void foo(); MAGIC2(__COUNTER__);
void bar(
int multiple,
float lines); MAGIC2(__COUNTER__);
void baz(); MAGIC2(__COUNTER__);
void quux(); MAGIC2(__COUNTER__);
static const int AFTER = __COUNTER__;
static const int COUNT = AFTER - BEFORE - 1; // 4
I took the initial value of __COUNTER__
because it might have been used previously in the source file, or some included header.
In C rather than C++ there are limitations on constant variables, so an enum
might be used instead.
enum MyEnum
{
FOO = COUNT // C: error: enumerator value for ‘FOO’ is not an integer constant
};
Replacing the const with enum
:
enum {BEFORE = __LINE__};
foo();
bar();
baz();
quux();
enum { COUNT = __LINE__ - BEFORE - 1};
enum MyEnum
{
FOO = COUNT // OK
};
I know that the OP's request is to use macros, but I would like to add another way of doing this that does not involve using macros.
C++20 introduces the source_location
class that represents certain information about the source code, such as file names, line numbers, and function names. We can use that pretty easily in this case.
#include <iostream>
#include <source_location>
static constexpr auto line_number_start = std::source_location::current().line();
void foo();
void bar();
static constexpr auto line_number_end = std::source_location::current().line();
int main() {
std::cout << line_number_end - line_number_start - 1 << std::endl; // 2
return 0;
}
And live example here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With