views:

56

answers:

3

Hi guys,

I have the following piece of code which doesn't compile when I try to instance something like CommandGlobal<int> because it tries to override virtual void Execute() const =0; with a function which returns int. It gives a non-covariance error.

class CommandBase
{
public:
    virtual void Execute() const =0;
};

template<class T>
struct CommandGlobal : CommandBase
{
    typedef boost::function<T ()> Command;
    Command comm;

    virtual T Execute() const
    {
        return comm();
    }
};

template<class T>
struct CommandMemberFunction : CommandBase
{
    typedef boost::function<T (int, std::string)> Command;
    Command comm;
    int entityid;
    std::string mfid;

    virtual T Execute() const
    {
        return comm(entityid, mfid);
    }
}; 

I have asked this question before and recieved an answer which I couldn't figure out exactly how to implement. The answer given is as follows:

Quick & dirty answer: pass to Execute a reference to the result type as a void*, and make Execute private. Then wrap Execute in a non-virtual wrapper which returns T by value and does the cast.

Could anyone clarify this answer with a bit of code. I would appreciate this greatly.

Thanks all!

A: 
Simon
A: 

You need a different name, try something like:

class CommandBase
{
public:
    virtual void Execute() const =0;
};

template<class T>
struct CommandGlobal : CommandBase
{
    typedef boost::function<T ()> Command;
    Command comm;

    virtual void Execute() const
    {
        ExecuteWithResult();
    }

    virtual T ExecuteWithResult() const
    {
        return comm();
    }
};
Ben Voigt
+1  A: 

I can't figure out how you're going to use this hierarchy. If you are going to do something like this:

CommandBase * cb = new CommandGlobal<int>();

then what will you put in your code for ??type?? below:

??type?? result = cb->Execute();

And if your going to do this:

CommandGlobal<int> cg;
int result = cg.Execute();

then why bother with a base class?

At any rate, you might also look into having Execute return a Boost.Any instance, as that way both the base class and the subclasses would all be returning instances of the same type. Then you could any_cast the result to the right type at the call site, presuming you could figure out which actual subclass of CommandBase you had.

SCFrench
I think you are right. I need to rethink my whole approach. Thanks for your input.
Sebastian Edwards