【问题标题】:Generalize the argument passed to boost::bind泛化传递给 boost::bind 的参数
【发布时间】:2018-08-29 14:31:59
【问题描述】:

我正在尝试编写一个使用 boost::bind 的通用结构 MyCounter 。我想要做的是编写MyCounter 这样通过更改其模板参数类型,我可以绑定到不同的方法。我的印象是,如果我将MyThread::send 之类的东西作为模板参数传递,我将能够直接在bind() 中使用它。显然我错了。你能帮我解决一些问题吗?谢谢

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <vector>
#include <utility>

struct MyThread //simplified
{
    void send1()
    {
        std::cout << "In Send1\n";
    }
    void send2()
    {
        std::cout << "In Send2\n";
    }
};

struct Job //ignore me
{
    Job(const unsigned int interval)
        : _tChk(0)
        , _tInterval(interval)
    {}

    void operator()(unsigned long nowSec)
    {
        if (nowSec > _tChk)
        {
            _functor();
            _tChk += nowSec + _tInterval;
        }
    }

private:
    unsigned long  _tChk;
    const unsigned int  _tInterval;

protected:
    boost::function<void()> _functor;
};

struct JobInvoker //ignore me
{
    typedef boost::shared_ptr<Job> JobPtr;
    JobInvoker(MyThread &myThread)
        : _myThread(myThread)
    {}

    template<typename JOB>
    void addJob(const unsigned int interval)
    {
        JobPtr job = boost::make_shared<JOB>(interval, _myThread);
        _jobs.push_back(job);
    }

    void operator() (JobPtr job)
    {
        (*job)(_now.tv_sec);
    }

    void invoke(timeval now)
    {
        _now = now;
        std::for_each(_jobs.begin(), _jobs.end(), *this);
    }

    timeval _now;
    std::vector<JobPtr> _jobs;
    MyThread &_myThread;
};

//my struggle
template<typename F>
struct MyCounter : public Job
{
    MyCounter(const unsigned int interval, MyThread &myThread)
    : Job(interval)
    {
        _functor = boost::bind(&F, &myThread); //<-- Error
    }
};

int main()
{
  MyThread t;
  JobInvoker jobInvoker(t);
  jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
  jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
  timeval now;//...
  jobInvoker.invoke(timeval now)
  return 0;
}

更新: 编译: g++ boost_f.cpp -lboost_system

我们得到以下错误:

boost_f.cpp: In constructor ‘MyCounter<F>::MyCounter(unsigned int, MyThread&)’:
boost_f.cpp:81:34: error: expected primary-expression before ‘,’ token
         _functor = boost::bind(&F, &myThread); //<-- Error
                                  ^
boost_f.cpp: In function ‘int main()’:
boost_f.cpp:89:46: error: type/value mismatch at argument 1 in template parameter list for ‘template<class F> struct MyCounter’
   jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
                                              ^
boost_f.cpp:89:46: error:   expected a type, got ‘MyThread::send1’
boost_f.cpp:89:51: error: no matching function for call to ‘JobInvoker::addJob(int)’
   jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
                                                   ^
boost_f.cpp:89:51: note: candidate is:
boost_f.cpp:52:10: note: template<class JOB> void JobInvoker::addJob(unsigned int)
     void addJob(const unsigned int interval)
          ^
boost_f.cpp:52:10: note:   template argument deduction/substitution failed:
boost_f.cpp:89:51: error: template argument 1 is invalid
   jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
                                                   ^
boost_f.cpp:90:46: error: type/value mismatch at argument 1 in template parameter list for ‘template<class F> struct MyCounter’
   jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
                                              ^
boost_f.cpp:90:46: error:   expected a type, got ‘MyThread::send2’
boost_f.cpp:90:51: error: no matching function for call to ‘JobInvoker::addJob(int)’
   jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
                                                   ^
boost_f.cpp:90:51: note: candidate is:
boost_f.cpp:52:10: note: template<class JOB> void JobInvoker::addJob(unsigned int)
     void addJob(const unsigned int interval)
          ^
boost_f.cpp:52:10: note:   template argument deduction/substitution failed:
boost_f.cpp:90:51: error: template argument 1 is invalid
   jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
                                                   ^
boost_f.cpp:92:29: error: expected primary-expression before ‘now’
   jobInvoker.invoke(timeval now)

【问题讨论】:

  • 不能使用 c++11 或更高版本吗?只是因为有 std::bind 而询问,而且对于 lambda,使用 bind 的需求极为罕见
  • 请在问题中包含错误。顺便说一句,F 是一个类型,而 boost::bind 需要一个值
  • @user463035818 不,我们不能:(
  • 那就最好使用C++98标签,希望你能把错误贴出来

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


【解决方案1】:

正如错误所说,成员函数不是类型,因此它不能用于模板类型参数。

相反,您需要使用非类型参数:

template<void(MyThread::*F)()>
struct MyCounter : public Job
{   
    MyCounter(const unsigned int interval, MyThread &myThread)
    : Job(interval)
    {
        _functor = boost::bind(F, &myThread);
    }
};

Live Example

请注意,我将F 设为指向MyThread 的成员函数的指针,而不是typename

【讨论】:

  • 太棒了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
相关资源
最近更新 更多