Marshallers

When I first mentioned return values, I said that more advanced handling of multiple return values was possible with Marshallers.

A Marshaller is a class that gets fed all the return values as they're returned. It can do a couple of things:

For example, if each slot returned an int, we could use a marshaller return the average value as a double. Or we could return all values in a std::vector<int>, or maybe stop as soon as the first slot returns 5.

As an example, here's the averaging marshaller:

class Averager
{
public:
    // we must typedef InType and OutType for the libsigc++ library
    typedef double OutType;
    typedef int InType;

    Averager()
      : total_(0), number_(0)
      {}


    OutType value() { return (double)total_/(double)number_; } // avoid integer division

    static OutType default_value() { return 0; }

    // This is the function called for each return value.
    // If it returns 'true' it stops here.
    bool marshal(InType newval)
    {
        total_ += newval; // total of values
        ++number_;        // count of values
        return false;     // continue emittion process
    };

private:
    int   total_;
    int   number_;
};

To use this, we pass the type as an extra template argument when defining the Signal, eg.

sigc::signal<int, Averager> mysignal;

Now we can do:

double average_of_all_connected_slots = mysignal();

Each connected slot will be called, its value passed to an instance of Averager and that Averager's value() will be returned.

In the downloadable examples, this is example6.cc.