C++;11-在编译时获取所有类变量,并在没有Boost的情况下为它们调用方法 我知道,在C++中,没有反射。然而,我需要在编译时迭代变量并为它们生成代码
我所拥有的是:C++;11-在编译时获取所有类变量,并在没有Boost的情况下为它们调用方法 我知道,在C++中,没有反射。然而,我需要在编译时迭代变量并为它们生成代码,c++,c++11,C++,C++11,我所拥有的是: class Foo { int x; double y; Foo() { Register(x, "x"); Register(y, "y"); } template <typename T> void Register(T val, const std::string & key){ //do something with val and key } } class-Foo{ i
class Foo {
int x;
double y;
Foo() {
Register(x, "x");
Register(y, "y");
}
template <typename T>
void Register(T val, const std::string & key){
//do something with val and key
}
}
class-Foo{
int x;
双y;
Foo(){
登记册(x,“x”);
登记册(y,“y”);
}
模板
无效寄存器(T val、const std::string和key){
//用val和key做点什么
}
}
但是,我想为每个变量自动调用Register
。有时,它们可能很多,很容易忘记注册某些内容或在key
中输入错误(key最好与变量名相同)
我曾经想到过类似于
CREATE\u和\u REGISTER(x,“x”)
macro的东西,但我不知道这是否可行。我见过一些基于Boost的解决方案,但我只需要普通的C+11/14。我认为不可能做到我们真正想要的(“无反射”),但是
我曾经想过创建和注册(x,“x”)宏,但我不知道这是否可行
我认为c宏是邪恶的,但是。。。如果您真的想要并且接受intx
和float y
被包装在结构中。。。我提出以下建议:
#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};
接收类型(int
,float
,…),名称(x
,y
,…)和默认值的
因此(如果默认值对您来说足够的话),您可以如下定义foo
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; }
};
foo () = default;
foo (int x0, float y0) : bx{x0, this}, by{y0, this}
{ }
如果您想要一个foo
构造函数,该构造函数可以创建具有不同(非默认值)的x
和y
,您可以确认默认构造函数(如果需要)并创建另一个构造函数,如下所示
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; }
};
foo () = default;
foo (int x0, float y0) : bx{x0, this}, by{y0, this}
{ }
如果您的Register()
方法(regis()
,在我的示例中)可以是静态
方法,则不需要在条###x
中使用指针,您可以简化一点示例
下面是一个完整的工作示例
#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};
}
#包括
#定义DEFandREGIS(类型、名称、定义)\
\
结构栏名称\
{ \
类型var\
\
bar###name(type val,foo*t):var{val}\
{t->regis(var,#name);}\
}; \
\
bar###name b###name{def,this};
结构foo
{
德范德雷吉斯(整数,x,1)
德范德雷吉斯(浮动,y,2.2f)
foo()=默认值;
foo(int x0,float y0):bx{x0,this},by{y0,this}
{ }
模板
void regis(T val,std::string const&key)
{std::虽然你知道没有反射,但你看不出你想要反射。生活有时是不公平的,我们对此无能为力。你为什么想要反射?看起来你可能想要使用map或者标签元组之类的东西。如果你仍然想在类字段上迭代,那么你需要做一些手工编写的r如中实现的eflection宏。如果您只想要“普通C++11/14”,那么您很可能只需要重新实现boost自己的现有内容。最简单(但很难看)方法是使用x-宏。看看这个答案-您可以使用相同的方法生成类成员列表和要注册的调用列表以始终同步谢谢。我知道,宏是邪恶的,但在这种情况下,用户编写宏比不忘记手动注册变量更方便。我是usi使用SQLite将其转换为类似ORM的东西,因此每个变量都用某种ORM逻辑“包装”在结构中:-)