1

I'm trying to connect a generic boost::function<void(void)> to many boost::signals2 of varying signature. I'm able to use boot::lambda::bind to do the binding part by passing the return value as part of the bind parameters, but have a problem when the return type is void

Example:

template<typename S>
class signal
{
 Connection VoidConnect(boost::function<void(void)> callback)
  {
    //if(boost::is_same<void, typename S::result_type>::value) // Doesn't seem to work
    if ( boost::is_void<typename S::result_type>::value )  // Doesn't seem to work
    {
       //GetSignal returns the actual boost signal
       // typename 'S' will be a boost::function with the same signature as the signal
      return GetSignal().connect( boost::lambda::bind(callback) );        
    }
    else
    {
      typename S::result_type f;
      return GetSignal().connect( (boost::lambda::bind(callback), f ) );
    }
  }
}

I keep getting compilation errors

error: variable or field ‘f’ declared void 
include/boost/function/function_template.hpp:132:42: error: void value not ignored as it ought to be

As can be seen from the error, the if condition with boost::is_void (neither is boost::is_same)doesn't seem to work, Does anybody know why? Is there a better way to do this binding?

Thanks, Sak

Sak
  • 269
  • 1
  • 4
  • 13

1 Answers1

2

You check this condition at runtime, so the both branches need to be correct in the compile-time (and they are obviously not). Instead, just specialize your template for void:

// WARNING: untested code!

template<typename S> 
class signal 
{ 
 Connection VoidConnect(boost::function<void(void)> callback) 
  { 
    typename S::result_type f; 
    return GetSignal().connect( (boost::lambda::bind(callback), f ) ); 
  } 
};

template<> 
class signal <void>
{ 
 Connection VoidConnect(boost::function<void(void)> callback) 
  { 
    return GetSignal().connect( boost::lambda::bind(callback) );         
  } 
};

If you want to use enable_if on the member function, you should define it to be a template. See the following code:

#include <boost/signals2.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>

using namespace boost::signals2;
class connect
{ 
public:
    template<typename S> 
    connection VoidConnect(boost::function<void(void)> callback, S &sig,
        typename boost::disable_if<boost::is_void<typename S::result_type> >::type *dummy = 0)
    {
    typename S::result_type res;  
    return sig.connect( (boost::lambda::bind(callback), *res) );  
    }

    template<typename S> 
    connection VoidConnect(boost::function<void(void)> callback, S &sig,
        typename boost::enable_if<boost::is_void<typename S::result_type> >::type *dummy = 0)
    {
    return sig.connect( boost::lambda::bind(callback) );          
    }

}; 


int main()
{
    boost::function<void(void)> f;
    signal<void(int)> sig1;
    connect s1;
    s1.VoidConnect(f, sig1);

    signal<int(int)> sig2;
    connect s2;
    s2.VoidConnect(f, sig2);
}
Igor R.
  • 14,716
  • 2
  • 49
  • 83
  • Hmm, Thanks for the soln, this template class signal is a big class with many functions, If specializing the entire template for void is not an option is there any other option? I'm currently looking if boost::enable_if can be used to achieve the selection at compile time. – Sak Aug 07 '12 at 15:45
  • The above example works fine for most of the signature types but doesn't compile when the signal signature contains combiners Eg: "signal sig3" Any Ideas why? – Sak Aug 13 '12 at 14:02
  • @Sak what is `Combiners::LogicalOrCombiner` and what errors do you get? – Igor R. Aug 14 '12 at 12:50
  • Sorry It's a internal struct and not a boost combiner, Any ways It's a combiner which calls every slot and if any of them returns true, then the value returned to the caller is also true. The combiner is used along with a signal (typedef boost::signals2::signal MySignalType) and the combiner is just a functor returning true or false. – Sak Aug 14 '12 at 13:40
  • In the meanwhile I have a similar query in http://stackoverflow.com/questions/11937425/what-is-wrong-with-this-boostlambdabind-usage which is really puzzling! – Sak Aug 14 '12 at 13:44