Thread: Covariance with virtual functions and stl containers

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    271

    Covariance with virtual functions and stl containers

    I have two classes, one derived from the other, and a virtual get function is supposed to return a pointer to a container with different element types depending on who's getting called. Simplified:

    Code:
    class A {
    public:
    virtual stl_container<T1>* get_something();
    };
    
    class B : public A {
    public:
    stl_container<T2>* get_something();
    };
    And no, the classes themselves are not templates.

    Anyway, when I try to compile this, it gives me an error message about "invalid covariant return types." So I thought it might help if the containers were recast into an isa relationship or something:

    Code:
    template <typename C = T1>
    class C1 : public stl_container<C> {};
    
    class C2 : public C1<T2> {};
    
    class A {
    public:
    virtual C1<>* get_something();
    };
    
    class B : public A {
    public:
    C2* get_something();
    };
    But that didn't work either.

    I'm almost tempted to return a void* and cast it as it comes out. Is there another solution?

    Oh, the reason the simplest solution (turning class A and B into a templated class) is not possible because the T1, T2 types are custom classes and different things are supposed to happen to them depending on the class.
    Last edited by cunnus88; 03-31-2009 at 07:12 PM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cunnus88
    I have two classes, one derived from the other, and a virtual get function is supposed to return a pointer to a container with different element types depending on who's getting called.
    Suppose you did manage to get this setup. How would you call this virtual function? What would be the type of the pointer used to store the return value of a call to this virtual function? It cannot be a pointer to stl_container<T1>, since a pointer to stl_container<T2> might be returned, and vice versa. Basically, you are unable to use polymorphism, since you have to know precisely at the site of the call which function is called in order to correctly store (or even use) its return value.

    I think that you need to relook your fundamental design here. What exactly are you trying to do?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Yeah, you're right. The more I think about it, it seems that I need to rethink my design.

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    templ<T1> and templ<T2> are never related, even if T1 and T2 are. There are very good reasons in type theory for this. In short, let's assume that for T2 : T1, templ<T2> : templ<T1>. Then, by the Liskov Substitution Principle, templ<T2> has to be usable everywhere a templ<T1> is. Since it's not allowed to insert a T1 into a templ<T2>, though, that is not given.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Hard to tell with the toy example classes, but I am always suspicious of the design of a class (other than a simple data class) that has get methods. The usual pattern followed is...

    Code:
    Stuff s = dumbObject.getStuff();
    // operate on s
    dumbObject.putStuff(s);
    Where it might be better to have something like...

    Code:
    smartObject.doStuff();
    But again, hard to tell without seeing real code.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. bind on member functions of stl containers
    By synss in forum C++ Programming
    Replies: 3
    Last Post: 07-03-2008, 04:38 AM
  2. Replies: 2
    Last Post: 10-02-2005, 05:04 PM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM