使用"奇怪的重复模板模式"的增量数字

Jir*_*Jir 1 c++ templates counter auto-increment crtp

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

让我们举个例子.执行以下代码后:

Address x;
Address y;
Run Code Online (Sandbox Code Playgroud)

x.addr应该是1,而y.addr应该是2.

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

TIA,吉尔

Ste*_*sop 7

你真的不需要它,因为你不需要捕获对象的破坏.您将注意到该维基百科页面上的示例保持该类型存在多少对象的运行总计,因此CRTP具有两个方便的功能:

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

如果您只想为单个类的每个成员创建一个唯一值,那么除了线程安全之外,您可以这样做:

int get_id() {
    static int counter = 0;
    return ++counter;
}

class Address {
    int addr;
  public:
    Address() : addr(get_id()) {}
};
Run Code Online (Sandbox Code Playgroud)

在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> {
};
Run Code Online (Sandbox Code Playgroud)

  • +1,`get_id`甚至可以是类的私有静态函数,使其更像是一个实现细节.请注意,如果您在多线程环境中运行,因为显示的解决方案不是线程安全的. (2认同)