Re: [sigc] How to use sigc::bind<>



with the help of several people from this list, i wrote for myself some code 
illustrating all the ways i had figured out to connect sigc's slots and 
signals.  here it is.

-tim




#include <iostream>
#include <sigc++/sigc++.h>
#include <sigc++/retype.h>
#include <sigc++/retype_return.h>


/*****************************************************************************
  This is intended to be an example of all the different ways you can connect
  libsigc++ signals to slots.  A slot can be a global function, static class
  function, or object function.
*****************************************************************************/

using namespace SigC;
using namespace std;


// These are sample callback functions.  There is no meaning intended by
// their contents, I just put something there to show that they were called.
void callback_void_return_no_parameters()
{
  cout << "callback_void_return_no_parameters()" << endl;
}

void callback_void_return_int_parameter(int i)
{
  cout << "callback_void_return_int_parameter(" << i << ")" << endl;
}

float callback_float_return_int_parameter(int i)
{
  return static_cast<float>(i) / 2;
}

int callback_int_return_float_parameter(float f)
{
  return static_cast<int>(f);
}

void callback_void_return_int_reference_parameter(int& i)
{
  cout << "Good luck binding to this!" << endl;
}

bool marshalled_callback_1()
{
  cout << "marshalled_callback_1()" << endl;
  return false;  // Not done handling signal.
}

bool marshalled_callback_2()
{
  cout << "marshalled_callback_2()" << endl;
  return true;  // Done handling signal.
}

bool marshalled_callback_3()
{
  cout << "marshalled_callback_3()" << endl;
  return false;  // Not done handling signal.
}


class SigCDerivedClass : public SigC::Object
{
/**
  This is a sample class used below to show how to connect a signal to
  non-static functions belonging to a class.

  In order to connect a signal to a slot made from a non-static function
  which is a member of a class, that class must derive from SigC::Object.
*/
  public:
    SigCDerivedClass() : SigC::Object() {};

    // You will get a compiler error if you don't impliment the destructor
    // in a class deriving from SigC::Object.
    ~SigCDerivedClass() {};

    void NonStaticFunction()
        { cout << "SigCDerivedClass::NonStaticFunction()" << endl; };
};

class NonSigCDerivedClass
{
/**
*/
  public:
    NonSigCDerivedClass();

    void NonStaticFunction();
    static void StaticClassFunction()
        { cout << "NonSigCDerivedClass::StaticClassFunction()" << endl; };
};

class BoolMarshal
{
  public:
    typedef bool OutType;
    typedef bool InType;

    BoolMarshal() {}

    OutType value() { return false; }

    static OutType default_value() { return true; }

    bool marshal(InType new_val)
    {
      return new_val;
    }

  private:
};


main()
{
  SigCDerivedClass object;
  Connection connection;

  // ******************************************************************
  // How to connect a signal with no parameters and void return type to
  // slots of varying signature.
  // ******************************************************************
  cout << "Calling a signal with void return type, no parameters:" << endl
       << "------------------------------------------------------" << endl;
  Signal0<void> signal_void_return_no_parameters;

  // A slot from a global function.
  signal_void_return_no_parameters.connect(
      slot(&callback_void_return_no_parameters) );

  // A slot from a static class function.
  signal_void_return_no_parameters.connect(
      slot(&NonSigCDerivedClass::StaticClassFunction) );

  // A slot from a function in an object.
  signal_void_return_no_parameters.connect(
      slot(object, &SigCDerivedClass::NonStaticFunction) );

  // A slot which expects an integer parameter.
  signal_void_return_no_parameters.connect(
      bind(slot(&callback_void_return_int_parameter), 10) );
  signal_void_return_no_parameters();
  cout << endl;
  // ******************************************************************


  // ******************************************************************
  // How to connect a signal with an integer parameter and void return
  // type to slots of varying signature.
  // ******************************************************************
  cout << "Calling a signal with void return type and an integer parameter:"
       << endl
       << "----------------------------------------------------------------"
       << endl;
  Signal1<void, int> signal_void_return_int_parameter;

  // A slot from a global function.
  signal_void_return_int_parameter.connect(
      slot(&callback_void_return_int_parameter) ); 

  // A slot with no parameters.
  signal_void_return_int_parameter.connect(
      hide<int>(slot(&callback_void_return_no_parameters)) );

  // A slot with which returns a float.
  signal_void_return_int_parameter.connect(
      hide_return(slot(&callback_float_return_int_parameter)) );
  signal_void_return_int_parameter(1);
  cout << endl;
  // ******************************************************************


  // ******************************************************************
  // How to connect a signal with an integer parameter and float return
  // type to slots of varying signature.
  // ******************************************************************
  cout << "Calling a signal with float return type and an integer parameter:"
       << endl
       << "-----------------------------------------------------------------"
       << endl;
  Signal1<float, int> signal_float_return_int_parameter;

  // A slot from a global function.
  connection = 
      signal_float_return_int_parameter.connect(
          slot(&callback_float_return_int_parameter)
      );
  cout << "signal_float_return_int_parameter(1) returns "
       << signal_float_return_int_parameter(1) << endl;
  connection.disconnect();

  // A slot which returns void.
  signal_float_return_int_parameter.connect(
      bind_return<float>(slot(&callback_void_return_int_parameter), 0.0) );
  cout << "signal_float_return_int_parameter(3) connected to" << endl
       << "\tcallback_void_return_int_parameter through bind_return" << endl
       << "\treturns " << signal_float_return_int_parameter(3) << endl;
  connection.disconnect();

  // A slot whose return type is int and that takes an integer parameter.
  signal_float_return_int_parameter.connect(
      retype<float, int>(slot(&callback_int_return_float_parameter)) );
  cout << "signal_float_return_int_parameter(9) connected to" << endl
       << "\tcallback_int_return_float_parameter through" << endl
       << "\tretype<float, int> returns "
       << signal_float_return_int_parameter(9) << endl;
  cout << endl;


  // This illustrates the order that call backs are called in, as a
  // consequence of the order they are connected to a signal.
  SigC::Signal0<bool> signal_order_example;
  signal_order_example.connect(slot(&marshalled_callback_1));
  signal_order_example.connect(slot(&marshalled_callback_2));
  signal_order_example.connect(slot(&marshalled_callback_3));
  cout << "These callbacks were connected in ascending order." << endl
       << "Here's what happens when the signal is emitted:" << endl;
  signal_order_example();
  cout << endl;


  // This illustrates how a marshaller affects callbacks.
  cout << "The marshalled callbacks are now connected to a signal which" << endl
       << "was instantiated with the BoolMarshaller class as its" << endl
       << "marshaller template parameter.  Notice it stops after" << endl
       << "callback_2, which returns true." << endl;
  SigC::Signal0<bool, BoolMarshal> signal_marshal_example;
//  SigC::Signal0<bool, Marshal<bool> > signal_marshal_example;
  signal_marshal_example.connect(slot(&marshalled_callback_1));
  signal_marshal_example.connect(slot(&marshalled_callback_2));
  signal_marshal_example.connect(slot(&marshalled_callback_3));
  signal_marshal_example();

  

  // **************************************************************************
  // Common errors (well, common to tim anyway)
  // ------------------------------------------
  // These are errors i tend to make repeatedly while trying to connect
  // signals to slots.  Uncomment the lines to see the type of error message
  // you will get if you too make these mistakes.
  // **************************************************************************
  // 1. Trying to make a slot out of a function of an object which doesn.t
  //    derive from SigC::Object.  This results in a link-time error.
  // NonSigCDerivedClass non_sigc_derived_object;
  // signal_void_return_no_parameters.connect(
  //    slot(non_sigc_derived_object, &NonSigCDerivedClass::NonStaticFunction));

  // 2. Trying to bind a signal to a slot which takes a reference parameter
  //    for the parameter being bound.  This results in a link time error
  //    because the compiler can't figure out you are tring to bind a
  //    reference to a variable (in this case an integer) instead of the
  //    integer itself, that is it when you bind an integer, it is looking
  //    for a function that takes an integer parameteter, not an integer
  //    reference parameter.  Even if the compiler was able to figure out
  //    you wanted to bind to a slot created from a function with a
  //    reference parameter, the example below would fail because you can't
  //    take a reference to the literal '1'.
  // signal_void_return_no_parameters.connect(
  //    bind(slot(&callback_void_return_int_reference_parameter), 1) );
   
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]