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

时间:2011-04-06 17:29:56

标签: c++ templates counter auto-increment crtp

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

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

Address x;
Address y;

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

为了实现这一目标,我在考虑Curiously Recurring Template Pattern。它可行吗? 此外,是否有更简单的方法来实现相同的行为?

TIA, JIR

5 个答案:

答案 0 :(得分:7)

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

  1. 因为它是一个基类,所以它的析构函数被调用(一个成员也会实现这个)。
  2. 因为它是派生类类型的模板,每个继承自它的类都有一个单独的计数器,包括层次结构中的不同类,如果它们使用多个继承来包含它们自己的CRTP基础,而不需要编写大量代码每个班级。
  3. 如果您只想为单个类的每个成员创建一个唯一值,那么除了线程安全之外,您可以这样做:

    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> {
    };
    

答案 1 :(得分:1)

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

答案 2 :(得分:0)

当然,您可以完全按照您引用的维基百科文章中的说明进行操作。 (除非它听起来好像你想减少dtor中的计数器。)或者,如果你只需要Address类,你可以做CRTP实现那样做一次性:

static int n_addresses = 0;
class Address {
  int addr;
  Address() { addr = ++n_addresses; }
};

或类似的东西。

答案 3 :(得分:0)

public class Address
{
    private static int addrCounter = 1;

    public int addr { get; private set; }

    public Address()
    {
        addr = addrCounter++;
    }
}

答案 4 :(得分:0)

您也可以使用类内部的静态计数器:

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