/************************************************************************** ** Title: demo program for use of CRTP, the curiously recurring ** template pattern for ** separating interface and implementation ** Date: 30.10.2008 ** Copyright: Bernard Haasdonk **************************************************************************/ #include #include using std::cout; using std::endl; using std::vector; /************************************************************************** ** Interface class with CRTP **************************************************************************/ template class VectorInterface { public: // definition of interface methods and forwarding call to derived class: // set all entries inline void setAll(const double& val) { asImp().setAll(val); } // size method inline int size() const { return asImp().size(); } // print method inline void print() { asImp().print(); } // access by [i] with integer i for read and write inline double& operator[](int i) { return asImp().operator[](i); } protected: // asImp() for CRTP, const and non-const version inline const VectorImp &asImp() const { return static_cast< const VectorImp& >( *this ); } inline VectorImp &asImp() { return static_cast< VectorImp& >( *this ); } }; /************************************************************************** ** Default Implementation class **************************************************************************/ template class DefaultVectorImplementation: public VectorInterface { public: DefaultVectorImplementation(const int size): // VectorInterface(size), size_(size) { } // default implementation of size inline int size() { return size_; } // default implementation of print by calling interface methods inline void print() { cout << "size: " << size_ << ", elements: "; for (int i=0;i < size_;i++) cout << this->operator[](i) << " "; cout << endl; } // default implementation of setAll by calling interface methods inline void setAll(const double& val) { for (int i=0; i < size() ; ++i) this->operator[](i) = val; } private: int size_; }; /************************************************************************** ** Specific Implementation 1 based on stl-vector class **************************************************************************/ class Vector1: public DefaultVectorImplementation { public: Vector1(const int size): DefaultVectorImplementation(size) { vec_.resize(size); } inline double& operator[](int i) { return vec_[i]; } // if you want to overload default method, simply implement a new one: //inline void print() //{ // cout << "Vector1.print() method! " << endl; // DefaultVectorImplementation::print(); //} // //inline void setAll(const double& val) //{ // for (int i=0; i < size() ; ++i) // vec_[i] = val; //} private: vector vec_; }; /************************************************************************** ** Specific Implementation 2 based on double array **************************************************************************/ class Vector2: public DefaultVectorImplementation { public: Vector2(const int size): DefaultVectorImplementation(size) { vec_ = new double[size]; } ~Vector2() { delete[] vec_; vec_ = 0; } inline double& operator[](int i) { return vec_[i]; } // if you want to overload default method, simply implement a new one: inline void setAll(const double& val) { // get pointer to one-after-last element double* endit = vec_ + size(); for (double* it= vec_; it!= endit; ++it) *it = val; } private: double* vec_; }; /************************************************************************** ** Main Program **************************************************************************/ template void test_vector(int size, double value) { VectorType vec(size); vec.print(); vec.setAll(value); vec.print(); vec[0] = vec[0] + 100.0; vec.print(); } int main() { test_vector(4,4.0); test_vector(8,8.0); }