C++ 如何使用标准函子进行curry
我有以下循环:C++ 如何使用标准函子进行curry,c++,C++,我有以下循环: MyList li; vector<Token*>::iterator itr = tokens.begin(); for (; itr != tokens.end(); ++itr) { li.add_string((*itr)->get_name()); } 不幸的是,我得到了那个讨厌的GCC模板编译错误 你能告诉我什么是正确的函子吗 我不能使用c++11 [编辑] 我的编译器不支持lamda 如果有帮助,以下是错误消息: /usr/lib/gcc
MyList li;
vector<Token*>::iterator itr = tokens.begin();
for (; itr != tokens.end(); ++itr) {
li.add_string((*itr)->get_name());
}
不幸的是,我得到了那个讨厌的GCC模板编译错误
你能告诉我什么是正确的函子吗
我不能使用c++11
[编辑]
我的编译器不支持lamda
如果有帮助,以下是错误消息:
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h: In instantiation of 'std::binder1st<std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> > >':
abc.c:823: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:100: error: no type named 'second_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:103: error: no type named 'first_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:106: error: no type named 'first_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:111: error: no type named 'second_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:117: error: no type named 'second_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h: In function 'std::binder1st<_Operation> std::bind1st(const _Operation&, const _Tp&) [with _Operation = std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >, _Tp = MyList*]':
abc.c:823: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward/binders.h:126: error: no type named 'first_argument_type' in 'class std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> >'
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/algorithm:62,
from abc.c:4:
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algo.h: In function '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<Token**, std::vector<Token*, std::allocator<Token*> > >, _Funct = std::binder1st<std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> > >]':
abc.c:824: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_algo.h:4200: error: no match for call to '(std::binder1st<std::binder2nd<std::mem_fun1_t<void, MyList, const std::string&> > >) (Token*&)'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../include/c++/4.4.7/backward/binders.h:在“std::binder1st”的实例化中:
abc.c:823:从此处实例化
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:100:错误:“class std::binder2nd”中没有名为“second_argument_type”的类型
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:103:错误:“class std::binder2nd”中没有名为“first_argument_type”的类型
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:106:错误:“class std::binder2nd”中没有名为“first_argument_type”的类型
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:111:错误:“class std::binder2nd”中没有名为“second_argument_type”的类型
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:117:错误:“class std::binder2nd”中没有名为“second_argument_type”的类型
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../include/c++/4.4.7/backward/binders.h:在函数“std::binder1st std::binder1st std::bind1st(const\u Operation&,const\u Tp&)[with _Operation=std::binder2nd,\u Tp=MyList*]”中:
abc.c:823:从此处实例化
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/backward/binders.h:126:错误:“class std::binder2nd”中没有名为“first_argument_type”的类型
在/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../include/c++/4.4.7/algorithm:62中包含的文件中,
来自abc.c:4:
/usr/lib/gcc/x86\u 64-redhat-linux/4.4.7/../../../../../../../../include/c++/4.4.7/bits/stl\u algo.h:在函数“\u Funct std::for_each(\u IIter,\u IIter,\u functt,\u functt)[with\u IIter=\u gnu cxx::\u normal u迭代器,\u Funct std::binder1st]”中:
abc.c:824:从此处实例化
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../../../../../../include/c++/4.4.7/bits/stl_-algo.h:4200:错误:调用“(std::binder1st)(令牌*&)”不匹配
[EDIT2]我现在知道为什么会出错了。bind2nd的实现如下:
template<typename _Operation, typename _Tp>
inline binder2nd<_Operation>
bind2nd(const _Operation& __fn, const _Tp& __x)
{
typedef typename _Operation::second_argument_type _Arg2_type;
return binder2nd<_Operation>(__fn, _Arg2_type(__x));
}
模板
内联装订机2
bind2nd(常数运算和常数fn,常数Tp和常数x)
{
typedef typename_操作::第二个参数_type_Arg2_type;
返回binder2nd(uu fn,_Arg2_type(uu x));
}
_操作是MyList::add_string中的mem_fun\t,这很好,因为mem_fun\t提供了operator()API
这里的问题是:_Arg2_type(uux),因为_Arg2_type是_Operation::second_argument_type,但是mem_fun_t没有second_argument_type属性,因为它是一元函数的子类
如果有人能确认我的类型转换跟踪,我将非常感激
谢谢Eric,你提到“bind1st和bind2d要求值是常量”让我很激动(但我认为你的措辞本身并不正确,因为关键不是值必须是常量,而是值必须是某种类型)
最后,GCC扩展组合是最好的解决方案;我确信boost具有同等功能。如果您的编译器支持它,您可以使用lambdas:
for_each(tokens.begin(), tokens.end(), [&li] (Token * val)
{
li.add_string(val->get_name());
} );
错误源于您试图将函数绑定为
MyList
的add\u string
方法的第二个参数bind1st
和bind2nd
要求值为常量,不适合将函数作为要绑定的值来接收
对于_,每个
都需要一个函数,该函数将迭代器作为其第一个参数。如果您真的坚持对每个使用,那么没有外部函数(相当于lambda,但不够优雅)就无法完成您想要完成的任务。此函数需要接收列表和令牌迭代器作为参数。然后,根据声明参数的顺序,可以使用bind1st
或bind2nd
将列表绑定到函数
让我们来看看这个函数:
void AddTokenNameToList(MyList& li, Token* token)
{
li.add_string(token->get_name());
}
您可以将此用于每个_
:
for_each(tokens.begin(), tokens.end(), std::bind1st(AddTokenNameToList, li));
如果列表参数被反转,您将使用bind2nd来绑定列表值
您可能会争辩说,这个函数是针对这种特殊情况定制的,不像只使用std方法那样优雅。我想你可能会发疯,把函数模板化,以接收应用于第一个参数和第二个参数的方法,但你真正想要的是一个lambda,因为你不能使用它们,这是你能得到的
然而,在这一点上,您不得不怀疑它是否真的节省了代码。这就是为什么bind1st和bind2nd名声不好,被认为几乎无用的原因之一。不过,它允许您使用其他一些不错的算法,因此它们仍然有一些优势。这不是一个很好的替代方案。如果没有C++11的lambdas,您已经拥有的就可以了。您想要转换-但首先您必须调整MyList,以便它可以用于STL算法。如果您不能使用C++11,您可以使用Boost吗<代码>boost::bind
比mem\u fun
@AlanStokes更有用,boost.Lambda;-)@模板不适用于直接函数调用。我一直认为Lambda库非常聪明,但从来没有发现它的用途。
for_each(tokens.begin(), tokens.end(), std::bind1st(AddTokenNameToList, li));