V
V
Vladimir Semenyakin2015-12-16 04:06:54
C++ / C#
Vladimir Semenyakin, 2015-12-16 04:06:54

How to create through macros a unique prefix to the generated type name at the compilation stage?

I'm trying to make a system to perform actions before the main() function is run. Needed to register meta-information about classes. I decided to do it through global variables in cpp files:

// Работает за счёт выполнения кода конструктора при инициализации глобальной переменной. До main
class BeforeMainHelper { public: BeforeMainHelper() { /* Before main start actions */ } } __helper__;

The problem arises when such registration is needed more than once within one cpp file. Problem for obvious reasons. Name conflict.
We need a mechanism for generating unique names for macros. In the beginning, I wanted to use the concatenated values ​​of the __line__ and __file__ built-in macros (a combination that uniquely specifies a line within the entire project). But __file__ is a string variable that cannot be concatenated as part of a variable name. To replace backslashes in the file path with underscores, I don't have enough black compile-time magic - I don't know how to do it.
I read about another macro "variable" - __counter__. Despite the fact that it is not included in the standard, I decided to try to come up with something with it. I ran into another problem - I need the same identifier twice (at the beginning for the type, then for the constructor). If you use __counter__ , it increments after the first use, and the names of the class and constructor become different.
Thus, I got into a dead end, from which I do not know how to get out. Now, during testing, everything works on concatenation with a line number. But you can't leave it like that - there can be very unpleasant, poorly caught bugs.
Help, please, if anyone has dealt with such things!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mace_UA, 2015-12-16
@semenyakinVS

You don't need to use __FILE__ , just put the classes in anonymous namespaces. Such classes will be unique for each compilation unit. Then it will be enough just to fasten __LINE__ to the identifier of the class object. And the class itself, alas, will have to be defined by a separate macro, since you need the ability to create several objects.
Here is a small example. Three file project.
The trick with concatenating a number and an identifier using macros is taken from here:
stackoverflow.com/questions/1597007/creating-c-mac...
"header.hpp":

#ifndef HEADER_HPP_INCLUDED
#define HEADER_HPP_INCLUDED

#include <iostream>

#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)

#define CLASS_MAGIC                                                           \
    namespace                                                                 \
    {                                                                         \
        struct FixedNameClass                                                 \
        {                                                                     \
            explicit FixedNameClass(int line)                                 \
            {                                                                 \
                std::cout << "Hello from \"" << __FILE__ <<                   \
                             "\", line " << line << std::endl;                \
            }                                                                 \
        };                                                                    \
    }

#define OBJECT_MAGIC                                                          \
    namespace                                                                 \
    {                                                                         \
        FixedNameClass TOKENPASTE2(variable_name_object, __LINE__)(__LINE__); \
    }

#endif // HEADER_HPP_INCLUDED

main.cpp:
#include "header.hpp"

CLASS_MAGIC
OBJECT_MAGIC
OBJECT_MAGIC
OBJECT_MAGIC

int main()
{
}

OBJECT_MAGIC
OBJECT_MAGIC

"other.cpp":
#include "header.hpp"

CLASS_MAGIC
OBJECT_MAGIC
OBJECT_MAGIC

Conclusion:
Hello from "other.cpp", line 4
Hello from "other.cpp", line 5
Hello from "main.cpp", line 4
Hello from "main.cpp", line 5
Hello from "main.cpp", line 6
Hello from "main.cpp", line 12
Hello from "main.cpp", line 13

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question