随机类的宏

Macros for random classes

本文关键字:随机      更新时间:2023-10-16

我有一个有几个子类的父类,并将添加一个函数,该函数随机生成并返回指向其中一个子类的指针。例如,

class Parent { ... }
class Child1 : public Parent {...}
class Child2 : public Parent {...}
...
class ChildN : public Parent {...}
// returns one of the children, randomly
Parent* generate_random();

一方面,我可以编写generate_random硬编码子类的数量,并在每次添加Parent的新子类或删除旧子类时更新此数量。但这似乎有点脆弱。类似地,我甚至可以使用const变量来跟踪子类的数量。同样,每当添加和删除类时,我都必须手动更新此表。这看起来也很脆弱。

相反,在像Python这样的语言中,我可以在Parent的每个子类的声明之上放置一个装饰器,它将增加所有子类的计数并使用它。例如:

_num_subclasses = 0
def _register_subclass(cls):
    global _num_subclasses
    _num_subclasses += 1
class Parent(object):
    ...
@_register_subclass
class Child1 (Parent):
    ...
@_register_subclass
class Child2 (Parent):
    ...
...

是否有一种方法可以使用预处理器做类似的事情?或者是否有一种方法可以在类声明之前或之后运行方法一次且仅一次?(如果我不仅可以为每个类增加一个计数器,还可以在单例映射中为它注册一个工厂,那就太好了。)或者,更一般地说,其他人是如何处理这类问题的?如果我的问题中有不清楚的地方或需要重新措辞,请告诉我。

我对python一窍不通,但让我们检查一下:

_num_subclasses = 0
def _register_subclass(cls):
    global _num_subclasses
    _num_subclasses += 1
@_register_subclass
class Child1 (Parent):

转换成c++ (ish)

int _num_subclasses = 0;
template<class cls>
bool _register_subclass() {
    _num_subclasses += 1;
    return true;
}
class Child1 : public Parent {
};
static const bool register1 = _register_subclass<Child1>();
但是,通常需要一个类型列表。通常像这样:
typedef std::unique_ptr<Parent*> ParentPointer;
//an enum is recommended, but type_id can work, depending on what you're doing
std::unordered_map<std::type_info, std::function<ParentPointer()>> _subclass_generator;
template<class cls>
bool _register_subclass() {
    _subclass_generator[typeid(cls)] = 
        []()->ParentPointer{
            return ParentPointer(new cls{});
        };
    return true;
}
class Child1 : public Parent {
};
static const bool register1 = _register_subclass<Child1>();

然后可以使用_subclass_generator

int selection = std::rand() % _subclass_generator.size();
auto& generator = *std::advance(_subclass_generator.begin(), selection);
ParentPointer ptr = generator(); //generates a Child.