我尝试使用lambdas在C ++ 11中编写FizzBuzz,但我得到了一个奇怪的编译器错误。
代码:
#include <iostream>
#include <string>
#include <sstream>
#include <list>
#include <algorithm>
using namespace std;
string fizzy(int n) {
int a = n % 3, b = n % 5;
if (a == 0 && b == 0) {
return "FizzBuzz";
}
else if (a == 0) {
return "Fizz";
}
else if (b == 0) {
return "Buzz";
}
else {
stringstream out;
out << n;
return out.str();
}
}
void fizzbuzz() {
string strings[100];
list<int> range(0, 100);
for_each(range.begin(), range.end(), [=](int i) {
strings[i] = fizzy(i);
});
for_each(range.begin(), range.end(), [=](int i) {
cout << strings[i] << endl;
});
}
int main() { fizzbuzz(); }
跟踪:
$ make
g++ -std=c++0x -o fizzy fizzy.cpp
fizzy.cpp: In lambda function:
fizzy.cpp:32:27: error: passing 'const std::string' as 'this' argument of 'std::basic_string<_CharT,
_Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(std::basic_string<_CharT, _
Traits, _Alloc>&&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<ch
ar>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]' discards qualifiers
make: *** [fizzy] Error 1
答案 0 :(得分:10)
你应该通过引用捕获,而不是通过lambda中的值捕获:
for_each(range.begin(), range.end(), [&](int i) {
// ^
strings[i] = fizzy(i);
});
这也恰好解决了这个问题 - 生成的lambda闭包的调用操作符默认标记为const
。
注意:强>
进行此编译的另一种方法是使用mutable
关键字,如下面的代码段所示:
for_each(range.begin(), range.end(), [=](int i) mutable {
// ^^^^^^^
strings[i] = fizzy(i);
});
mutable
关键字具有在生成的lambda闭包的调用运算符中删除const
的效果。
但是,我相信你确实不想要这样:为什么修改数组中的字符串,你会忘记函数何时返回?
通过引用捕获将解决您的问题。
<强>更新强>
正如Daniel Frey在评论中指出的那样,这条指令:
list<int> range(0, 100);
将创建一个大小为零的列表,其元素(其零元素)全部用值100初始化。可能不是您想要的。您可能希望将其更改为以下内容(std::iota
仅在您使用C ++ 11时可用,否则您必须展开自己的分配循环):
#include <algorithm>
list<int> range(100); // Creates a list of 100 elements
iota(begin(range), end(range), 0); // Assigns value 0..99 to those elements
答案 1 :(得分:1)
此更改应修复它,因此您可以通过引用捕获:
for_each(range.begin(), range.end(), [&strings](int i) {
strings[i] = fizzy(i);
});
同样,Daniel和Andy指出,range
的初始化可能不是您所期望的,因为它创建了zero
大小的列表:
list<int> range(0, 100);