我被迫使用一个 C api,它定义了一堆与下面非常相似的代码
// Some old obscure c api
// First bunch of class in namespace ns
struct _ns_A { int a; };
struct _ns_AResponse { int resp; };
// Second bunch of classes in another ns
struct _ns2_B { int b; };
struct _ns2_BResponse { int resp; };
// Lots more classes in more namespaces...
// Bunch of parsing classes in namespace ns
_ns_AResponse* parse_A(_ns_A* a)
{
// do some work
return new _ns_AResponse { a->a * 100 };
}
// Parsing class in another ns
_ns2_BResponse* parse_B(_ns2_B* b)
{
// do some work
return new _ns2_BResponse { b->b * 100 };
}
// And so on....
它为每个命名空间和类型创建了一个解析函数,而不是使用重载函数。它还强制客户端代码管理内存。
为了帮助解决这个问题,我编写了一些类似于以下内容的代码:
// EXAMPLE Expansion: std::unique_ptr<_ns_AResponse> parse(_ns_A* a) { auto ret = parse_A(a); return std::unique_ptr<_ns_AResponse>(ret); }
#define REGISTER_INVOKER(NS, TYPE) inline std::unique_ptr<_##NS##_##TYPE##Response> parse(_##NS##_##TYPE* t) \
{ auto ret = parse_##TYPE(t); return std::unique_ptr<_##NS##_##TYPE##Response>(ret); }
// Register a single parse function for each of our types, stipulating namespace and class
REGISTER_INVOKER(ns, A);
REGISTER_INVOKER(ns2, B);
REGISTER_INVOKER(for 1000s of other types)
int main()
{
// Invoke our parse method with our unique_ptr to _ns_A
auto a = std::make_unique<_ns_A>();
auto a_ret = parse(a.get());
// And so on...
auto b = std::make_unique<_ns2_B>();
auto b_ret = parse(b.get());
}
上面允许我们有一个单独的 parse 调用,它不仅为我们管理内存使用,而且按类型重载,以允许我们以更面向 c++ 的方式使用它。
我的问题如下:
有没有更合适的方法来做到这一点而不必求助于使用宏?我充分利用了 C++17 和 boost。除非我被迫这样做,否则我宁愿不必用宏污染我们的代码库。