【问题标题】:How to use boost::is_same in c++ template along with boost::lambda::bind如何在 c++ 模板中使用 boost::is_same 以及 boost::lambda::bind
【发布时间】:2012-08-07 14:14:03
【问题描述】:

我正在尝试将通用 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 也不是)似乎不起作用,有人知道为什么吗?有没有更好的方法来做这个绑定?

谢谢, 萨克

【问题讨论】:

    标签: boost boost-bind boost-function boost-lambda boost-signals2


    【解决方案1】:

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

    【讨论】:

    • 嗯,谢谢你的解决,这个模板类信号是一个有很多功能的大类,如果将整个模板专门化为 void 不是一个选项,还有其他选项吗?我目前正在研究是否可以使用 boost::enable_if 在编译时实现选择。
    • 以上示例适用于大多数签名类型,但当信号签名包含组合器时无法编译例如:“signal sig3” 任何想法为什么?
    • @Sak Combiners::LogicalOrCombiner 是什么,你遇到了什么错误?
    • 对不起这是一个内部结构而不是一个boost组合器,无论如何它是一个调用每个槽的组合器,如果它们中的任何一个返回true,那么返回给调用者的值也是true。组合器与信号一起使用(typedef boost::signals2::signal MySignalType),组合器只是一个返回真或假的函子。
    • 同时我在stackoverflow.com/questions/11937425/… 有一个类似的查询,真是令人费解!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多