5

ラムダを使用して C++11 で FizzBu​​zz を記述しようとしていますが、奇妙なコンパイラ エラーが発生します。

コード:

#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
4

2 に答える 2

10

ラムダで値によってキャプチャするのではなく、参照によってキャプチャする必要があります。

for_each(range.begin(), range.end(), [&](int i) {
//                                    ^
    strings[i] = fizzy(i);
    });

これもたまたま問題を解決します-生成されたラムダクロージャーの呼び出し演算子はconstデフォルトでマークされています。


ノート:

これをコンパイルする別の方法はmutable、以下のスニペットのようにキーワードを使用することです。

for_each(range.begin(), range.end(), [=](int i) mutable {
//                                              ^^^^^^^
    strings[i] = fizzy(i);
    });

このmutableキーワードにはconst、生成されたラムダ クロージャの呼び出し演算子を削除する効果があります。

しかし、私はあなたが本当にこれを望んでいないと信じています.関数が戻ったときに忘れる配列内の文字列を変更するのはなぜですか?

参照によってキャプチャすると、問題が解決します。


アップデート:

コメントで Daniel Frey が指摘したように、この指示は次のとおりです。

list<int> range(0, 100);

サイズがゼロのリストを作成します。その要素 (ゼロ要素) はすべて値 100 で初期化されます。おそらく、必要なものではありません。次のように変更することもできます ( std::iotaC++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
于 2013-03-19T20:17:21.543 に答える
1

この変更で修正されるはずなので、参照してキャプチャします。

for_each(range.begin(), range.end(), [&strings](int i) {
  strings[i] = fizzy(i);
});

また、DanielとAndyが指摘しているように、の初期化は、サイズ設定されたリストrangeを作成するため、おそらく期待したものではありません。zero

list<int> range(0, 100);
于 2013-03-19T20:18:49.840 に答える