How to store data for reflection in preprocessor stage

Started by
11 comments, last by Randy Gaul 9 years, 1 month ago

Hey, I have just been studying how to implement reflection in the simplest and least expensive way possible in c++.

I've been studying up on macros, since those are all pre-processor, but I can't seem to find a way to accomplish what I am trying to do.

Sorry if this sounds kinda stupid. I am just sorta learning this stuff. I want to write a macro function that takes a string literal (for a variable or function name), and put it in a vector. The only problem is, I don't know how to create a vector in the preprocessing stage.

I was wondering if it is possible to create some sort of 'macro class' or struct to store this data, so that I can use this for later.

For example, I want to do something like this:


Psuedo-code:
#include <iostream>
#include <string>
#include <vector>

#define struct ReflectionData /
{/
    std::vector<string> names;/
}

#define ADD_REFLECTION_DATA(std::string data) (ReflectionData.names.push_back(data))

ADD_REFLECTION_DATA("mario")
ADD_REFLECTION_DATA("luigi")

int main()
{
    std::cout << ReflectionData.names[0];
    std::cout << ReflectionData.names[1];
    std::cout << ReflectionData.names[2];

    return 0;
}

ADD_REFLECTION_DATA("Bowser")

Output:
Mario
Luigi
Bowser

Any idea how to accomplish something like this?

View my game dev blog here!

Advertisement
Not sure what you're after but the preprocessor is totally unaware of C++ constructs like structs.
It runs before the compiler even starts munching through your code and acts as a text replacer.

Not sure what you're after but the preprocessor is totally unaware of C++ constructs like structs.
It runs before the compiler even starts munching through your code and acts as a text replacer.

I want the program to store strings inside of a vector during the preprocessor stage, and then output the data after it has been compiled during runtime. I eventually want to also store boost::function_pointers to functions in the classes, and use the data for metaprogramming, so that other classes can call each others functions without circular dependencies, similar to what Unity and UE4 does.

View my game dev blog here!

Ok, I still haven't figured out how to do it but I managed to get somewhere closer to the answer, and this article helped: http://www.randygaul.net/2012/10/01/c-reflection-type-metadata-introduction/

here is the code that I wrote:


#include <windows.h>

#include "reflector.h"

int main()
{
	REFL_ADD_NAME("mario");
	std::string reflectName = ReflectionManager::names[0];

	std::cout << '\n' << reflectName;
	return 0;
}


#ifndef REFLECTOR_H_
#define REFLECTOR_H_

#include <iostream>
#include <string>
#include <vector>

class ReflectionManager
{
public:
    static std::vector< std::string > names;

    static const void AddName(std::string name)
    {
        names.push_back(name);
    };
};

std::vector< std::string > ReflectionManager::names;

#define REFL_ADD_NAME(NAME)(ReflectionManager::AddName(NAME))

#endif /* REFLECTOR_H_ */

Unfortunately this doesn't work if I place the REFL_ADD_NAME("mario"); function outside of main, which leads me to believe that the macro function is being called at runtime. Ugh. I wan't the macro to be called only at the preprocessing stage. Any info on how to do this?

View my game dev blog here!

You can not run code outside of a function (with the exception of putting it into a constructor for a static variable in C++). Thats basic C/C++ knowledge. Maybe you should first learn a language before shoehorning concepts of other languages into the already most complicated language or simply just use the other language when you need features from it?

Ignoring what you're even trying to do, the preprocessor commands mostly just act as find and replace, they tend to either copy text from one place to another or do light processing of text before pasting it in(as is the case with macros.)

The preprocessor doesn't understand concepts like classes, it will never know what a vector is and honestly I don't know why you're attempting this when the code you've shown so far lacks a very basic understanding of what the code is actually doing at different stages. When anything is being "called" it is going to be during runtime.

You can not run code outside of a function (with the exception of putting it into a constructor for a static variable in C++). Thats basic C/C++ knowledge.

*sigh, I understand you can't run code outside a function, that's why i'm asking for help. Afaik Boost::mpl has a good solution that runs preprocessor code outside of functions and during compile time using template metaprogramming. I might use that instead.

View my game dev blog here!

I think you are approaching it the wrong way.

If you want things to happen at compile time, you need to only use constructs that are compile time.

Your problem isn't the macros, but what they expand into.

Any function calls, unless they are constexpr is out of the question, you simply can't get .push_back to work in compile time, not even if you wrap it in another function call or any number of macros or templates.

You need to find some other way to construct your reflection data map which is compile time only, if that is what you want.

If you really want to understand macros, I suggest searching your compiler for a way to output the preprocessed cpp file so you can see how they expand.

In MSVC you can right click on a cpp file, select "Properties", expand "C/C++", select "Preprocess", and set "Preprocess to a File" to "Yes". Then just right-click on that one file and compile it - it won't actually build it into a program, but it will produce a text file on disk that you can then open in MSVC to see the output. (Remember to change the option back to "No" in order to actually build your program again!)

To make a long story short though as several people have said, macros are copy-paste. If you can't do what you're trying to do with Ctrl+C and Ctrl+V by hand, you can't do it in macros.

Addendum - Heavy macro use is generally frowned upon in C++, especially as templates have gotten more powerful in the later iterations of the language. They do not understand any C or C++ features and do not respect scoping rules. While there are still some things that only they can do (conditional compilation, for example), that list is rapidly shrinking.

I want the program to store strings inside of a vector during the preprocessor stage, and then output the data after it has been compiled during runtime. I eventually want to also store boost::function_pointers to functions in the classes, and use the data for metaprogramming, so that other classes can call each others functions without circular dependencies, similar to what Unity and UE4 does.

Uh, at least what Unreal does for their reflection involves a custom preprocessing code-generator. Their macros I belive only serve as input for their own preprocessing tool, which then generates the actual code in a seperate header file (called Header.h.generated in their case). So unfortunately I don't belive that what you want to do can be done without writing your own compiler/processing tools/routines.

This topic is closed to new replies.

Advertisement