本文為 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 {};
沒有留言:
張貼留言