1

我正在尝试将泛型连接boost::function<void(void)>到许多不同签名的 boost::signals2 。我可以使用 boot::lambda::bind 通过将返回值作为绑定参数的一部分传递来执行绑定部分,但是当返回类型为 void 时会出现问题

例子:

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 ) );
    }
  }
}

我不断收到编译错误

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

从错误中可以看出,带有 boost::is_void 的 if 条件(boost::is_same 也不是)似乎不起作用,有人知道为什么吗?有没有更好的方法来做这个绑定?

谢谢,萨克

4

1 回答 1

2

您在运行时检查此条件,因此两个分支在编译时都需要正确(显然不是)。相反,只需将您的模板专门用于 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) );         
  } 
};

如果要在成员函数上使用 enable_if,则应将其定义为模板。请参阅以下代码:

#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);
}
于 2012-08-07T15:14:32.900 回答