考虑下面的宏。如何使用宏展开for循环并将大量宏干净地导出到可读的标题中?
macro.h
#define ARR(n) \
typedef int arr##n[n]; \
void arr##n##_add(arr##n res, arr##n x, arr##n y){ \
int i = 0; \
for (; i < n; i++) { \
res[i] = x[i] + y[i]; \
} \
}
ARR(3)
ARR(4)
使用gcc -E -P macro.h > out.h
通过预处理器执行此操作,我们得到:
out.h
typedef int arr3[3];
void arr3_add(arr3 res, arr3 x, arr3 y){
int i = 0;
for (; i < 3; i++) {
res[i] = x[i] + y[i];
}
}
typedef int arr4[4];
void arr4_add(arr4 res, arr4 x, arr4 y){
int i = 0;
for (; i < 4; i++) {
res[i] = x[i] + y[i];
}
}
使用上面的token pasting,我们避免重复定义。现在有两件事我想知道:
如何用例如
替换(展开)每个for(;i; i < n)
res[0] = x[0] + y[0];
res[1] = x[1] + y[1];
...
res[n] = x[n] + y[n];
将大量宏hackery导出到可读标头的简洁方法是什么?我应该在make
文件中创建一个shell函数,将最终标题导出到include
目录吗?
也许有更好的方法可以做到这一点。欢迎任何替代品。
答案 0 :(得分:1)
以下是此answer使用these macro functions引用的一种可能解决方案:
# our DBFactory component, from some model package
class DBFactory(object):
def __init__(self, db_url, **kwargs):
db_echo = kwargs.get('db_echo', False)
self.engine = create_engine(db_url, echo=db_echo)
self.DBSession = sessionmaker(autoflush=False)
self.DBSession.configure(bind=self.engine)
self.metadata = Base.metadata
self.metadata.bind = self.engine
def get_session(self):
session = self.DBSession()
return session
# we instantiate them in the __init__.py file, and save on registry
def main(global_config, **settings):
"""runs on server start, returns a Pyramid WSGI application """
config = Configurator(
settings=settings,
# ask for a custom request factory
request_factory = MyRequest,
)
config.registry.db1_factory = DBFactory( db_url=settings['db_1_url'] )
config.registry.db2_factory = DBFactory( db_url=settings['db_2_url'] )
# and our custom request class, probably in another file
class MyRequest(Request):
"override the pyramid request object to add explicit db session handling"
@reify
def db1_session(self):
"returns the db_session at start of request lifecycle"
# register callback to close the session automatically after
# everything else in request lifecycle is done
self.add_finished_callback( self.close_dbs_1 )
return self.registry.db1_factory.get_session()
@reify
def db2_session(self):
self.add_finished_callback( self.close_dbs_2 )
return self.registry.db2_factory.get_session()
def close_dbs_1(self, request):
request.db1_session.close()
def close_dbs_2(self, request):
request.db2_session.close()
# now view code can be very simple
def my_view(request):
# get from db 1
stuff = request.db1_session.query(Stuff).all()
other_stuff = request.db2_session.query(OtherStuff).all()
# the above sessions will be closed at end of request when
# pyramid calls your close methods on the Request Factory
return Response("all done, no need to manually close sessions here!")
这是一个问题,但是以一种令人费解的,hacky,丑陋的方式......特别是,使用递归宏来进行迭代操作。