本文為 C++ Software Design 書的第 26 節內容。
template <typename Derived> struct DenseVector { public: Derived& derived() { return static_cast<Derived&>(*this); } Derived const% derived() const { return static_cast<Derived const&>(*this); } size_t size() const { return derived().size(); } decltype(auto) operator[](const size_t index) { return derived()[index]; } decltype(auto) begin() { return derived().begin(); } decltype(auto) end() { return derived().end(); } }上面 base class 即為 DenseVector 的抽象。接下來要實作 derived class:
template <typename T> class DynamicVector : public DenseVector<DynamicVector<T>> { public: size_t size() const; }這樣就完成了 Dynamic Vector 與 DenseVector 之間在編譯時期的繼承關係。要注意的是 decltype(auto) 的使用:這樣就不用在 base class 去推敲要用哪一種型態。 在 C++ 20 引入 Concept 的觀念後,可以利用 Concept 與 tag class 來實作 CRTP 的 base class:
struct DenseVectorTag {}; template <typename T> struct IsDenseVector : public std::is_base_of<DenseVectorTag, T> {}; template <typename T> constexpr bool IsDenseVector_v = IsDenseVector<T>::value; template <typename T> concept DenseVector = /* concepts */ && IsDenseVector_v<T>;這個 tag class 的用途是確保指有需要的類別會符合 DenseVector 的 concept,其他的類別都不會實作出來。而 derived class 有兩種實作的方法:
// Intrusively template <typename T> class DynamicVector : private DenseVectorTag { // implementations }; // Non-intrusively template <typename T> class StaticVector { // implementations }; template <typename T> struct IsDenseVector<StaticVector<T>> : public std::true_type {};
沒有留言:
張貼留言