alwaysLearning0 39 Junior Poster

Hi,

I was thinking of writing this post as a reply of Need small example for compile time polymorphism and runtime polymorphism in c++.

But later decided to open this new thread as some expert may want to give some expert opinion on this.

On the above mentioned thread, mike_2000_17 has given some example of c++ static/dynamic polymorphism. I have gave an example of java static polymorphism.

Here is another way to write static polymorphism in C++ using CRTP Idiom.

I have used same classes in this post what we have used in the above thread.

template <typename T>
class Animal{

public:
	void makeCry(){
		T &self = *static_cast<T *>(this); //CRTP
		self.doCry();
	}
};

class Dog : public Animal<Dog>{
public:
	void doCry() {
		std::cout << "Woof Woof!" << std::endl;
	};
};

class Cat : public Animal<Cat>{
public:
	void doCry() {
		std::cout << "Miaou.." << std::endl;
	};
};

template <typename T>
void makeCry(T &animal){
	animal.makeCry();
}

int main() {

	Dog dog;
	Cat cat;
	makeCry(dog);
	makeCry(cat);


	return 0;
}

Main benefit of this is:
1) No virtual function, so no vtable. Base class does not need to add any virtual functions. It can help you to add more functionality without changing base class header.
2) static_cast happend on compile time, so minimal runtime overhead.

That is one use case of CRTP Idioms.
Here is another interesting one. Implement one operator in derived class, for example <, and you can have all other operator from Base class.

template <typename T>
class Ordered{
public:
	bool operator>=(const T &other){
		T &myself = *(static_cast<T *>(this));
		return other < (myself);
	}

	bool operator!=(T &other){
		T &myself = *(static_cast<T *>(this));
		return (other < myself) &&  !(myself < other);
	}

	bool operator==(T &other){
		T &myself = *(static_cast<T *>(this));
		return !(myself != other);
	}
};

/*CuriousCaseOfTemplate is a derived class which just implemented its own < operator. Ordered has injected other operator in it. ;) Look at the main()*/
class CuriousCaseOfTemplate: public Ordered<CuriousCaseOfTemplate>{
	int a;
public:
	CuriousCaseOfTemplate(int a): a(a){
	}

	bool operator<(const CuriousCaseOfTemplate &other) const{
		return a < other.a;
	}


};

int main() {

	CuriousCaseOfTemplate a(2), b(4), c(4);

	assert(a<b);
	assert(b>=a);
	assert(b!=a);
	assert(b==c);
}

I hope it helps to understand CRTP.

mike_2000_17 commented: Nice! I rarely use CRTP, might do so in the future! +14
m4ster_r0shi commented: Cool. Now, I'd like to see an example with the parametric base class pattern (PBCP). (CRTP is also known as the parametric subclass pattern (PSCP)) +7