C++ std::for_每个忽略默认函数参数
我偶然发现了一个奇怪的编译问题。我想使用C++ std::for_每个忽略默认函数参数,c++,boost,std,C++,Boost,Std,我偶然发现了一个奇怪的编译问题。我想使用std::for_each处理字符串列表。以下简化代码说明了该问题: # include <list> # include <string> # include <algorithm> using namespace std ; void f(wstring & str) { // process str here } void g(wstring & str, int dummy = 0)
std::for_each
处理字符串列表。以下简化代码说明了该问题:
# include <list>
# include <string>
# include <algorithm>
using namespace std ;
void f(wstring & str)
{
// process str here
}
void g(wstring & str, int dummy = 0)
{
// process str here, same as f, just added a second default dummy argument
}
int main(int, char*[])
{
list<wstring> text ;
text.push_back(L"foo") ;
text.push_back(L"bar") ;
for_each(text.begin(), text.end(), f) ; // OK, fine :)
for_each(text.begin(), text.end(), g) ; // Compilation error, complains about
// g taking 2 arguments, but called within std::for_each
// with only one argument.
// ...
return 0 ;
}
谢谢你的帮助
注意:我刚开始学习英语,很抱歉出错:)默认参数只是一个代码生成工具,不是函数签名的一部分,因此您无法真正解决这个问题。您可以将函数包装到函数对象中,但这正是
bind
为您所做的
但是,在C++0x中,您可以方便地存储结果(并使用std::bind
),以使代码更具可读性:
auto trimmer = std::bind(boost::algorithm::trim<std::wstring>, std::placeholders::_1, std::locale());
std::for_each(text.begin(), text.end(), trimmer);
我认为它对函子来说根本不起作用。删除伪参数。我添加到
g
的伪参数是为了演示std::for_each
的奇怪行为。用一些类似于g(str)
的wstring str
调用g
就像一个符咒,但不是在std::for_each
中。在我的例子中,如果没有技巧,直接使用boost::algorithm::trim
作为函子是不可能的,因为它的第二个参数是可选的(一个std::locale)@Overcoder:这是因为g(str)
立即变成g(str,0)
——默认参数只是代码生成糖。这是我从代码中所期望的,但事实并非如此。以下是MinGW报告的内容:d:\development\tools\mingw32\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_algo.h:4185:2:错误:参数太少function@overcoder:这并不“奇怪”。此外,如果您坚持当前标准,请查看bind2nd(确实它对函数有一些要求-你的g应该是从二进制函数继承的结构)@vnm:是的,很好,少了一个boost依赖项:std::for_each(…,…,std::bind2nd(boost::algorithm::trim,std::locale())
。谢谢!我会看看是否可以为我当前的项目启用C++0x。Lambdas似乎更方便。@过度编码:由你决定——绑定语法并不是那么糟糕,只是味道的问题。在这里有这一行并不是世界末日,它仍然是非常自解释的代码。。。
auto trimmer = std::bind(boost::algorithm::trim<std::wstring>, std::placeholders::_1, std::locale());
std::for_each(text.begin(), text.end(), trimmer);
std::for_each(text.begin(), text.end(), [](std::wstring & s){ boost::algorithm::trim<std::wstring>(s); });