The Welder
The Welder

Reputation: 1062

Returning multiple class types from a function

If I have a simple program as follows:-

class Program
{
    public:
       my_func(void)                 \\ What return type do I use here??
       {
            switch (i)               \\ assume i comes from somewhere...
            {
                case 1:
                {
                    Glue g;
                    g.init();
                    return g;
                }
                case 2:
                {
                    Wood w;
                    w.init();
                    return w;
                }
                ....
            }
        }
}

Can someone tell me how I can set the return type of this function to be an object created in one of the switch cases? Also because of time constraints, I can't use new/delete for creating the objects or I'd just return a void* ptr. The objects created in the switch are sufficiently large, so is it possible to create them in each case and return a reference to them, without them going out of scope?

Upvotes: 1

Views: 491

Answers (4)

pmr
pmr

Reputation: 59811

One solution to the first problem is the obvious: get a hierarchy and return a base type. An alternative solution is to use a Variant type, like Boost.Variant. Then you could define your return type as: boost::variant<Wood, Glue>. This is often the preferable approach when a hierarchy would be unnatural or would add complexity. On the other hand the hierarchy approach is simpler to execute and some people don't eschew the template magick that comes with Variant classes.

Please be aware that rolling your own Variant type can be a quite complex undertaking and prefer a library.

Your second question boils down to: get a better compiler. Both a recent version of clang and gcc 4.8 report warnings for both functions.

Upvotes: 3

Lzh
Lzh

Reputation: 3635

For your first question, it's good design to define a base class from which the possible types of the objects returned derive. For example, let Glue and Wood derive from a class called Carpenter or CarpenterObject, you'll need in it an indicator of what the object is actually.

class Carpenter
{

public:

    static const int UNKNOWN = -1; //example only
    static const int GLUE = 0;
    static const int WOOD = 1;

    virtual int Type() { return UNKNOWN; }

    Carpenter* GetSomething();

};

class Glue: public Carpenter
{
    virtual int Type() { return Carpenter::GLUE; }
};

class Wood: public Carpenter
{
    virtual int Type() { return Carpenter::WOOD; }
};

Carpenter* Carpenter::GetSomething()
{
    Glue* g = new Glue();
    Wood* w = new Wood();

    return g; // or w
}

void main()
{
    Carpenter p;
    cout<<p.GetSomething()->Type();
}

I think the second question deals with a warning not an error (it works normally with me), but I'm using Visual Studio 2012's compiler.

Upvotes: 1

stardust
stardust

Reputation: 5988

The first problem can be solved by using the second questions approach. That is make Glue and Wood inherit from the same base class and pass reference to the function. This way you don't have to return a reference of a local variable and you can return the type you wanted.

struct Obj {

    virtual void init() { cout << "Obj"; }
};

struct Wood : public Obj {
    virtual void init() { cout << "Wood"; }
};


struct Glue : public Obj {
    virtual void init() { cout << "Glue"; }
};

struct Program {

    // Pass by reference the actual object. You want it created it here?
    // Why just create it outside. i.e move your case to the place where you know what i 
    // is. It doesn't have to be created here.
    void foo(Obj& o) { 
        o.init(); 
    }
};



int main()
{
    Program p;
    Obj* ref_p;

    // Move your case here.
    //case
        Wood w;
        ref_p = &w;
    // 
        //Glue g;
        //ref_p = &g;

    p.foo(*ref_p);
}

Upvotes: 2

Mohit Shah
Mohit Shah

Reputation: 862

First program template concept applied incorrectly

as you have to pass the type replacing T when calling the function.

Second program i compiled in my compiler and it gives warning for both the functions

Upvotes: 0

Related Questions