Provided the following template:

template <class T>
class MyTemplate {
	private:
		T myData;
	public:
		MyTemplate(const T &data) : myData(data) {}
		bool Contains(const T &);
};

Is there a way to ensure at compile time that the argument T derives from another class?

I want T to derive from my abstract class Comparable, so that it implements CompareTo and I can call that method from Contains (and other methods) instead of using operators (== < >) which T would have to overload.

I provided the simplest example of MyTemplate, which would make more sense if it where, for example, a linked list (so Contains traverses it and calls CompareTo for each element).

Thanks.

Recommended Answers

All 8 Replies

Hey, thanks for your reply.

I'm not ever going to derive anything from my template (MyTemplate).

I just wan't to force the user of MyTemplate to provide a class as the template argument (T) which has the CompareTo method (and thus derives from an abstract Comparable class).

For example:

class SomeClass {
	private:
		//...
	public:
		SomeClass();
		//...
};

MyTemplate<SomeClass> var; //ERROR, SomeClass doesn't implement CompareTo!

class Comparable {
	public:
		virtual int CompareTo(Comparable &) = 0;
};

class ComparableClass : Comparable {
	private:
		//...
	public:
		ComaprableClass();
		virtual int CompareTo(ComparableClass &);
		//...
};

MyTemplate<ComparableClass> var; //CORRECT, ComparableClass implements CompareTo!

Maybe there is a desing pattern for doing this...

You don't have to do this.
It will be a very nice thing if your compiler will point out the error for you. In this case it will. Just tell the user of your class that you can only templatize those classes which have the CompareTo function. This way, if user will try to pass another class as T, the compiler would raise an error. What can be good than that. Compiler has already solved your problem

>MyTemplate<SomeClass> var;
Most compilers will give you an error not only on the line that attempts to use a member that a derived template class doesn't possess, but also the line that the class in question was instantiated.

The best solution is always the simplest one that does the trick. So, since you're only instantiating it with one type (i.e., a Comparable and it's derivatives), you don't need a template. That's what JohnA was saying.

class Comparable
{
public:
    virtual int compare( const Comparable& c ) const = 0;
};


class IsComparable : public Comparable
{
public:
    int compare( const Comparable& c ) const
    {
        return 0;
    }
};


class MyClass
{
private:
    const Comparable& myData;
public:
    MyClass( const Comparable& data ) : myData( data ) {}

    bool Contains( Comparable& c )
    {
        return myData.compare( c );
    }
};


int main()
{
    IsComparable isComp;
    MyClass myClass( isComp );
    // ...
}

Thanks nucleon, but I never said I was only instantiating MyTemplate with only one class, in fact MyTemplate is an AVL and I want it to be able to hold any type, for example int or my own String class.

There should be a way in ISO C++ to tell the compiler that the template class argument should derive from some class(es).

Forget my last post, I just got what you ment by:

only instantiating it with one type (i.e., a Comparable and it's derivatives)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.