使用"Curiously Recurring Template Pattern"的增量数字

Incremental number using the "Curiously Recurring Template Pattern"

本文关键字:数字 Template Curiously Recurring 使用 Pattern      更新时间:2023-10-16

我想实现一个class Address,当创建时,将其字段addr初始化为唯一的值。每次创建Address实例时,该值必须增加1。

让我们举个例子。在执行了以下代码之后:

Address x;
Address y;

x.addr为1,y.addr为2。

为了实现这一点,我想到了奇怪的循环模板模式。这可行吗?此外,是否有更简单的方法来实现相同的行为?

TIA,Jir

这里并不需要它,因为您不需要捕获对象的销毁。您会注意到,Wikipedia页面上的示例保存了该类型对象的总数,因此CRTP有两个方便的特性:

  1. 因为它是基类,所以调用它的析构函数(成员也可以实现这一点)。
  2. 因为它是在派生类类型上模板化的,所以每个从它继承的类都有一个单独的计数器,包括层次结构中的不同类,如果它们使用多重继承来每个类都包含自己的CRTP基,而不需要为每个类编写大量代码。

如果你只想让一个类的每个成员都有一个唯一的值,那么撇开线程安全不谈,你可以这样做:

int get_id() {
    static int counter = 0;
    return ++counter;
}
class Address {
    int addr;
  public:
    Address() : addr(get_id()) {}
};

在CRTP示例之后,如果您有多个要跟踪的类并希望它们每个都有自己的id空间,则可以模板化get_id并使用Address作为参数。

对于这个用例,如果你使用CRTP,你可以把数据成员addr放在模板基类中,如果你有很多类,这是一个胜利,因为使用它的每个类的类型更少:

template <typename Derived>
class unique_addr {
  protected:
    int addr;
    unique_addr() : addr(get_id<Derived>()) {}
};
class Address : public unique_addr<Address> {
};
class OtherAddress : public unique_addr<OtherAddress> {
};

对于你想做的事情来说,这似乎有点小题大做了。如果您只需要一个惟一的值,请使用一个静态整数,并在每次实例化对象时增加它。然后将每个实例(即非静态)变量设置为该值。

当然,您可以完全按照您引用的Wikipedia文章中所示的方法进行操作。(除了它听起来不像是你想要减少dr中的计数器。)或者,如果您只需要Address类使用它,那么您可以一次性执行那里的CRTP实现所做的事情:

static int n_addresses = 0;
class Address {
  int addr;
  Address() { addr = ++n_addresses; }
};
public class Address
{
    private static int addrCounter = 1;
    public int addr { get; private set; }
    public Address()
    {
        addr = addrCounter++;
    }
}

你也可以在类内部使用静态计数器:

class Address
{
  static int s_Count; // define this variable in appropriate cpp file
  int addr;
public:
  Address () : addr(++ s_Count) {}
};