I don't think it's possible to do what do exactly want ("no reflection") but ...
I have thought of something like CREATE_AND_REGISTER(x, "x") macro, but I dont know if it is possible
I think c-macros are distilled evil but... if you really want and if you accept that int x
and float y
are wrapped in structs... I propose the following macro
#define DEFandREGIS(type, name, def) \
\
struct bar_##name \
{ \
type var; \
\
bar_##name (type val, foo * t) : var{val} \
{ t->regis(var, #name); } \
}; \
\
bar_##name b##name{def, this};
that receive the type (int
, float
, ...), the name (x
, y
, ...) and a default value
So (if default values are enough for you) you can define foo
as follows
struct foo
{
DEFandREGIS(int, x, 1)
DEFandREGIS(float, y, 2.2)
template <typename T>
void regis (T val, std::string const & key)
{ std::cout << "regis(" << val << ", \"" << key << "\")" << std::endl; }
};
and, defining a foo
variable, you get printed
regis(1, "x")
regis(2.2, "y")
If you want a foo
constructor that can create x
and y
with different (not default values), you can confirm the default constructor (if you want) and create another constructor as follows
foo () = default;
foo (int x0, float y0) : bx{x0, this}, by{y0, this}
{ }
If your Register()
method (regis()
, in my example) can be a static
method, there is no need of this
pointer in bar##x
and you can simplify a little the example.
The following is a full working example
#include <iostream>
#define DEFandREGIS(type, name, def) \
\
struct bar_##name \
{ \
type var; \
\
bar_##name (type val, foo * t) : var{val} \
{ t->regis(var, #name); } \
}; \
\
bar_##name b##name{def, this};
struct foo
{
DEFandREGIS(int, x, 1)
DEFandREGIS(float, y, 2.2f)
foo () = default;
foo (int x0, float y0) : bx{x0, this}, by{y0, this}
{ }
template <typename T>
void regis (T val, std::string const & key)
{ std::cout << "regis(" << val << ", \"" << key << "\")" << std::endl; }
};
int main()
{
foo a;
foo b{3, 4.4f};
}