首页 > 解决方案 > C++ 如何避免不同第三方类型变量的重复代码?

问题描述

我有一个管理许多不同但相似类型的相似成员变量的类。

class Manager {
  Type1 a;
  Type2 b;
  Type3 c;
  void process();
};

尽管类型不同,但它们共享一些功能和属性。至少这让我可以使用一些模板函数以类似的方式处理类成员。

template <typename T>
void process(T& t) {
  // do something with t
}

void Manager::process() {
  process(a);
  process(b);
  process(c);
}

在我的程序中,我还需要提供与成员变量名称相等的字符串。

template <typename T>
void print(T t, std::string name) {
  std::cout << name << ": " << t.msg << std::endl;
}

void Manager::print() {
  print(a, "a");
  print(b, "b");
  print(c, "c");
}

我已经减少了代码示例来说明我的问题。实际上,在更多的地方,我只需为每个变量复制粘贴整个代码块。时不时地,添加一个具有新类型的新成员变量。

我可以使用什么模式来避免这些看似不必要的类似代码重复?

我想到了类似的东西std::map<std::string, ParentType> members;。我想这将允许我遍历所有成员变量而不是复制粘贴代码,并且我还可以为每个变量存储一个相应的名称字符串。但是,我使用的类型没有公共父类,是第三方的,即无法修改///的Type1实现...Type2Type3

我想我真正想要的是只有一个地方可以定义类型和名称,然后能够简单地循环所有变量以执行类似的处理。

我可以考虑使用预处理器宏来部分解决这个问题,但是在现代代码中不是很不鼓励吗?

标签: c++design-patternspolymorphism

解决方案


It seems like this is exactly the use case for the preprocessor---removing repeating code and stringifying identifiers. If you don't like it, and you don't mind the horrible syntax, you could make Manager a tuple:

class Manager {
    std::tuple<Type1, Type2, Type3 /* more types can be added ... */> tup;
}

Then you can run a function on each element using std::apply. See Template tuple - calling a function on each element.

void Manager::process() {
    std::apply([](auto ...x){
        std::make_tuple(process(x)...);
    }, this->tup);
}

Without reflection I believe there is no cleaner solution. And your stringify print example is impossible without macros.


推荐阅读