簡體   English   中英

使用`this`作為指向CRTP中基類的派生類的指針

[英]Using `this` as a pointer to derived class in a base class in CRTP

我正在嘗試使用CRTP來注冊某些類的所有實時(已創建但尚未銷毀)實例。 這對我很有用:

template <typename T>
class Registrable {
  public:
    void _register(T* p) { instances_.insert(p); }
    void _unregister(T* p) { instances_.erase(instances_.find(p)); }
    static const std::set<T*> & instances() { return instances_; }
  private:
    static std::set<T*> instances_;
};

template <typename T>
std::set<T*> Registrable<T>::instances_;

class Class : private Registrable<Class> {
  public:
    using Registrable<Class>::instances;
    Class() { _register(this); }
    Class(const Class &) { _register(this); }
    Class(Class &&) { _register(this); }
    ~Class() { _unregister(this); }
    void function() { }
};

int main() {
  Class c;
  auto upc = std::make_unique<Class>(c);
  std::vector<Class> vc(5);
  for (auto i : Class::instances())
      i->function();
}

編輯:

更好的是不關心在派生類中注冊和取消注冊實例。 根據@ Jean-BaptisteYunès和@Aconcagua的解決方案:

template <typename T>
class Registrable {
  public:
    static const std::set<T*> & instances() { return instances_; }
  protected:
    Registrable() { instances_.insert(static_cast<T*>(this)); }
    Registrable(const Registrable &) : Registrable() { }
    Registrable(Registrable &&) : Registrable() { }
    ~Registrable()  { instances_.erase(instances_.find(static_cast<T*>(this))); }
  private:
    static std::set<T*> instances_;
};

...

class Class : public Registrable<Class> { ... }

但是, 我也不確定這種鑄件是否安全 特別是,如果Class還將通過多重繼承從另一個類派生。

@ amc176的答案聲稱,我可以假設演員會成功,但我更願意確定。 根據@Aconcagua的評論,我可以肯定,這不是答案。

static_cast不進行運行時檢查以確保static_cast轉換是完全安全的。 無論如何,如你所知,類型T將是一個可Registrable<T>的派生類,你可以假設演員表會成功。

實際上,在cppreference中提到了這種強制轉換通常在應用CRTP時使用(在鏈接中稱為static polymorphism )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM