【问题标题】:Boost function and boost bind: Bind the return value?Boost函数和boost绑定:绑定返回值?
【发布时间】:2011-12-19 02:21:35
【问题描述】:

这与上一个问题有关:Using boost::bind with boost::function: retrieve binded variable type

我可以像这样绑定一个函数:

在.h中:

class MyClass
{
    void foo(int a);
    void bar();
    void execute(char* param);
    int _myint;
}

在.cpp中

MyClass::bar()
{
    vector<boost::function<void(void)> myVector;
    myVector.push_back(boost::bind(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
    boost::function<void(void)> f  = myVector[0];
    _myint = atoi(param);
    f();
}

但是我怎样才能绑定一个返回值呢?即:

在.h中:

class MyClass
{
    double foo(int a);
    void bar();
    void execute(char* param);
    int _myint;
    double _mydouble;
}

在.cpp中

MyClass::bar()
{
    vector<boost::function<void(void)> myVector;
    //PROBLEM IS HERE: HOW DO I BIND "_mydouble"
    myVector.push_back(boost::bind<double>(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
    double returnval;
    boost::function<void(void)> f  = myVector[0];
    _myint = atoi(param);
    //THIS DOES NOT WORK: cannot convert 'void' to 'double'
    // returnval = f();
    //MAYBE THIS WOULD IF I COULD BIND...:
    // returnval = _mydouble;

}

【问题讨论】:

  • 你有一个function&lt;void(void)&gt;——你认为double会出现在哪里?如果您想要一个返回 double 的空值 function&lt;&gt;,请尝试 function&lt;double()&gt;...
  • bar函数的最后一行,输入参数是这样绑定的,函数类型被擦除变成function&lt;void(void&gt;&gt;,但_myint仍然是链接的..我想要返回值也一样。关键是能够将所有 boost::functions 存储在同一个向量中;)
  • 但是你已经明确指定你想要void作为返回值(function&lt;void(void)&gt;);要么你想要void,要么你想要double,你不能同时拥有。
  • 我同意 returnval = f(); 不应该工作,但应该有一种方法来绑定返回值,就像有一种方法来绑定输入值......
  • 不,Boost.Bind 绑定函数和参数。函数的执行和结果的返回值与调用常规函数完全相同。

标签: c++ boost boost-bind boost-function


【解决方案1】:

如果您想要的是一个返回 void 的空函数,但在执行此操作之前将值分配给 _myDouble,结果为 foo(),那么您不能仅使用 Boost.Bind 轻松完成此操作。但是,Boost 有另一个库专门针对这类事情——Boost.Phoenix

#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/phoenix/phoenix.hpp>

struct MyClass
{
    MyClass() : _myVector(), _myInt(), _myDouble() { }
    void setMyInt(int i);
    void bar();
    void execute();

private:
    double foo(int const a) { return a * 2.; }

    std::vector<boost::function<void()> > _myVector;
    int _myInt;
    double _myDouble;
};

void MyClass::setMyInt(int const i)
{
    _myInt = i;
}

void MyClass::bar()
{
    using boost::phoenix::bind;

    _myVector.push_back(
        bind(&MyClass::_myDouble, this) =
            bind(&MyClass::foo, this, bind(&MyClass::_myInt, this))
    );
}

void MyClass::execute()
{
    if (_myVector.empty())
        return;

    _myVector.back()();
    double const returnval = _myDouble;
    std::cout << returnval << '\n';
}

int main()
{
    MyClass mc;
    mc.bar();

    mc.setMyInt(21);
    mc.execute();      // prints 42
    mc.setMyInt(3);
    mc.execute();      // prints 6  (using the same bound function!)
                       // i.e., bar has still only been called once and
                       // _myVector still contains only a single element;
                       // only mc._myInt was modified
}

【讨论】:

  • 这看起来很有趣,正是我需要的,我明天试试,谢谢
  • 啊,我刚刚找到了学习凤凰的动力。很酷的东西
【解决方案2】:

问题 1:myVector 需要是类成员。 问题 2:myVector 对返回双精度且不带参数的函数感兴趣,即boost::function&lt;double()&gt;

然后,要将 _mydouble 绑定到 foo 的参数,请调用 boost::bind(&amp;MyClass::foo, this, MyClass::_mydouble),它会在调用 foo 时向您提供有关将 double 转换为 int 的编译警告。

最接近 Boost.Bind 的方法是提供 toreturn 作为参数。

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>

using namespace std;

class Foo {
        int myInt;
        double myDouble;
public:
        Foo() : myInt(3), myDouble(3.141592) { }
        void SetToMyInt(double& param)
        {
                param = myInt;
        }
        void SetToMyDouble(double& param)
        {
                param = myDouble;
        }
        double Execute()
        {
                double toReturn = 2;
                boost::function<void(double&)> f = boost::bind(&Foo::SetToMyDouble, this, _1);
                f(toReturn);
                return toReturn;
        }

};

int main() {
        Foo foo;
        std::cout << foo.Execute() << std::endl;
        return 0;
}

【讨论】:

  • boost::function&lt;double(void)&gt; 请不要传播这种可怕的 C 主义,更喜欢 boost::function&lt;double()&gt;
  • 1: myVector 显然是一个类成员 :P 并查看 cmets 了解它为何对 &lt;void(void)&gt; 函数感兴趣
  • 不,不明显。使用 ideone.com 之类的工具将您的代码归结为显示您的问题的内容,然后发布您的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 2014-03-02
相关资源
最近更新 更多