lambda表达式中的C ++模板函数

时间:2010-02-26 18:03:22

标签: c++ templates lambda functor

这篇第一篇文章已经由Eric的评论解决了,但是引发了我在水平规则之后描述的次要问题。谢谢埃里克!

我正在尝试将一个模板类的仿函数传递给boost thread_group类的create_thread方法以及两个参数到仿函数。但是我似乎无法超越我当前的编译错误。使用以下代码:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>

using namespace boost::lambda;
using namespace std;

namespace bl = boost::lambda;

template<typename ftor, typename data>
class Foo
{
public:
    explicit Foo()
    {
    }
    void doFtor ()
    {
        _threads.create_thread(bind(&Foo<ftor, data>::_ftor, _list.begin(), _list.end()));
        //_threads.create_thread(bind(_ftor, _list.begin(), _list.end()));
        _threads.join_all();
    }

private:
    boost::thread_group _threads;
    ftor _ftor;
    vector<data> _list;
};

template<typename data>
class Ftor
{
public:
    //template <class Args> struct sig { typedef void type; }

    explicit Ftor () {}

    void operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
    {
        for_each(startItr, endItr, cout << bl::_1 << constant("."));
    }
}

我也尝试过typedefing'type',因为我认为我的问题可能与Sig模板有关,因为函子本身是模板化的。

我得到的错误是:

error: no matching function for call to ‘boost::lambda::function_adaptor<Ftor<int> Foo<Ftor<int>, int>::*>::apply(Ftor<int> Foo<Ftor<int>, int>::* const&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>> >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’
事先带了一堆序言。

提前感谢您的帮助!


好的,我已经修改了以下Eric建议中的代码,导致以下代码:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>

using namespace boost::lambda;
using namespace std;

namespace bl = boost::lambda;

template<typename ftor, typename data>
class Foo
{
public:
    explicit Foo()
    {
    }
    void doFtor ()
    {
        _threads.create_thread(bl::bind(boost::ref(_ftor), _list.begin(), _list.end()));
        _threads.join_all();
    }

private:
    boost::thread_group _threads;
    ftor _ftor;
    vector<data> _list;
};

template<typename data>
class Ftor
{
public:
    typedef void result_type;

    explicit Ftor () {}

    result_type operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
    {
        for_each(startItr, endItr, cout << bl::_1 << constant("."));
        return ;
    }
};

然而,这会导致另一个编译错误:

/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: no match for call to ‘(Ftor<int>) (const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’
ftor.h:41: note: candidates are: void Ftor<data>::operator()(typename std::vector<data, std::allocator<_CharT> >::iterator&, typename std::vector<data, std::allocator<_CharT> >::iterator&) [with data = int]
/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: return-statement with a value, in function returning 'void'

似乎已将void定义为result_type,现在期望operator()返回一些东西。我尝试从函数中返回result_type,但这也产生了错误。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

Sig(或者在您的情况下,只需要typedef void result_type;

IIRC,lambda :: bind生成其参数的const副本。

因此,使用非const运算符()的仿函数存在问题。这可以通过包装(在doFtor()中)使用Ftor :: operator()const 来解决,_ftor使用boost :: ref

迭代器存在类似的问题。在这里包装boost :: ref将无法直接工作,因为它最终会使用对临时的引用。更简单的解决方案是修改Ftor :: operator()以通过副本获取其参数。

最简单的是修改Ftor,使其operator()为const 它通过副本获取其参数:

void operator() (typename vector<data>::iterator startItr, typename vector<data>::iterator endItr)const

如果你真的不能创建Ftor :: operator()const,你可以修改doFtor()如下(但是仍然需要让Ftor :: operator()通过副本获取它的参数):

_threads.create_thread(bind(boost::ref(_ftor), _list.begin(), _list.end()));