Conditionally apply template types in C ++

I have a class template that should be able to compare between two objects, through comparison objects obtained from the Compare class, which I have:

 template<typename T> class Container { public: template<typename A, typename B> class Compare { public: virtual bool eq(const A&, const B&) const = 0; }; 

I provide default comparison objects if type T has the == operator:

  template<typename A, typename B> class Default : public Compare<A,B> { public: bool eq(const A& a, const B& b) const { return a==b; } }; private: Compare<T,T>* comparison_object; bool uses_default; Container() : comparison_object(new Default<T,T>()), uses_default(true) {} Container(Compare<T,T>& cmp) : comparison_object(&cmp), uses_default(false) {} ~Container() { if(uses_default) delete comparison_object; } }; 

However, when I try to compile this with a custom class, it does not have < operator== overloads (even if I provide an object derived from Compare ):

 MyObjCmp moc; Container<MyObj>(&moc); 

The compiler complains that the statement does not exist:

 error: no match for 'operator==' (operand types are 'const MyObj' and 'const MyObj') 

This makes sense because the Default class still needs to be created, even if I don't need it. But now I need a workaround ...

Any ideas?

+6
source share
2 answers

Instead of checking the runtime for a null pointer, you can use compile-time checking without an object:

 Container() : comparison_object(new Default<T,T>), uses_default(true) {} Container(Compare<T,T>& cmp) : comparison_object(&cmp), uses_default(false) {} 

The default constructor, and therefore Default , will only be created if necessary, so there is no error when using a constructor other than the default with a type for which Default will fail.

But be careful with juggling such rude pointers; this is a recipe for memory leaks and worse. Do not forget that the virtual destructor for Compare and the rule of three) , and be very careful that the default comparator is not unexpectedly destroyed. Better yet, use the smart pointer to take care of all this.

+4
source
 template<typename T1, typename T2 > class Container { public: template<typename T3, typename T4 > class Compare { public: virtual bool eq(const T1&, const T2&) const = 0; }; class Default : public Compare { public: bool eq(const T1& a, const T2& b) const { return a==b; } }; private: Compare<T1,T2>* comparison_object; bool uses_default; Container(Compare<T1,T2>* cmp) : comparison_object(cmp), uses_default(false) { if (!cmp) { comparison_object = new Default<T,T>(); uses_default = true; } } ~Container() { if(uses_default) delete comparison_object; } }; 
0
source

Source: https://habr.com/ru/post/978830/


All Articles