0

In Java, there is a detailed generic class hierarchy for containers. Java defines interfaces like ICollection<T> which is inherited by ISet<T> which is inherited by IList<T> and implemented by ArrayList<T>. I would like to create a similar hierarchy in a C++ library I am creating.

Using C++ templates however, makes this very cumbersome. For example, say I define an ISet<T>:

    template<typename T>
    class ISet
    {
    public:
        virtual ~ISet() = 0;
        virtual void add(T e) = 0;
        virtual size_t size() = 0;
        virtual bool isEmpty()
        {
            return size() == 0;
        }
    };

Then, if I wanted to make a List<T> which implements ISet<T>, I would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet<T>->isEmpty():

template<typename T>
class List : public ISet<T>
{
public:

    ...

    void add(T e)
    {
        ...
    }

    virtual sz size()
    {
        ...
    }

    using ISet<T>::isEmpty; //well this is annoying
};

I understand the reason for this, and "why doesn't this work the way I expect it to?" has been answered in these qeustions: here and here.

My question is, is there a clean (or even any!) way to achieve this without having to explicitly list every inherited but not overridden method in the base class?

What I would really like would be something I could put in List<T> like:

using ISet<T>::*;

which would make all of the methods in ISet<T> dependent in the class definition of List<T>, and would alias them to List<T>::functionName.

Please tell me there is SOME way to achieve this without having to update every inheriting class's list of using directives each time I change one of my templated interfaces!

Do I have to resort to a preprocessor define of using directives defined along with the interface? Arrrrgghhhh!

Community
  • 1
  • 1
datademon
  • 3
  • 2
  • 3
    so you want to create a library, which implements inheritance nightmare on purpose? wondering who would use it :) btw there is a nice implementation of std containers – BЈовић Sep 25 '13 at 18:28
  • 1
    `using ISet::isEmpty;` is not absolutely necessary. It is necessary ONLY IF you want to call this function from other member functions, without using `this->` or `base::isEmpty()`. For users, it is not necessary, they can call this function even if you don't write that. Now the question is, do you call `isEmpty` from other functions? How frequently? I think you can just type few more characters once in a while: `this->isEmpty()` and you're done. – Nawaz Sep 25 '13 at 18:31
  • Of course there are STL containers. The STL uses "concepts" which are just uninforced contracts for the naming and implementation of member functions. I would like the compiler to enforce implementation constraints (an ISet must implement an add function, for example), as well as allow me to treat the containers generically, for example an algorithm which adds items to an ISet without knowing what ISet implementation it is using. – datademon Sep 25 '13 at 18:33
  • 1
    I didn't ask "is this a good idea?" I asked how to do it. – datademon Sep 25 '13 at 18:34
  • @datademon: There is NO WAY you can do it. – Nawaz Sep 25 '13 at 18:35
  • 1
    C++ is not Java. If you want Java class hierarchy, you know where to find it. – n. m. could be an AI Sep 25 '13 at 18:40
  • "I would have to list in the class definition every method that I wanted to inherit but not override" ― no you wouldn't have to. – n. m. could be an AI Sep 25 '13 at 18:47
  • "for example an algorithm which adds items to an ISet without knowing what ISet implementation it is using" — we are able to do that already without any kind of hierarchy, thankyouverymuch. – n. m. could be an AI Sep 25 '13 at 18:56

1 Answers1

1

This statement is incorrect:

... would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet->isEmpty():

Try to compile following code:

template<class T>
class Base {
public:
   virtual void f1();
   virtual void f2();
};

template<class T>
class Derived : public Base<T> {
public:
   virtual void f1();
};

void foobar()
{
   Derived<int> d;
   d.f1();
   d.f2();
}

If you mean that you want to access base class methods or members on derived class, you can simply do that more explicit way:

template<class T>
class Derived : public Base<T> {
public:
   virtual void f1() { this->f2(); }
};

That is not messy and works as you asked, just little bit more explicit (some says it is good idea to always use this-> explicitly).

Slava
  • 43,454
  • 1
  • 47
  • 90
  • By the way, it turns out my problem was [shadowing in the derived class by a function with a different signature](http://stackoverflow.com/questions/411103/function-with-same-name-but-different-signature-in-derived-class). Thanks for answering! – datademon Sep 25 '13 at 19:20