2013-03-19 40 views
5

我想在使用lambdas的C++ 11中編寫FizzBu​​zz,但是我收到了一個奇怪的編譯器錯誤。帶lambda的FizzBu​​zz.cpp?

代碼:

#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 
+6

'list range(0,100);'不*做你認爲它做的事。 – 2013-03-19 20:17:52

+1

這對於''for_each'永遠是效率最低的。 – 2013-03-19 20:26:19

+0

除非你讓你的lambda'mutable',否則值捕獲是不變的。 – 2013-03-19 20:27:10

回答

10

你應該捕獲通過在拉姆達參考,而不是捕捉由值:

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

這也正好解決問題 - 生成的羊羔的調用操作符da閉合默認標記爲const


注:

的另一種方式,使這個編譯是使用mutable關鍵字,如下面的代碼片段:

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

mutable關鍵字丟棄的效果const在生成的lambda閉包的調用操作符中。

但是,我確實相信你真的這麼做不是想要這樣:爲什麼修改數組中的字符串,當函數返回時你會忘記這些字符串?

通過引用捕獲將解決您的問題。


UPDATE:

正如丹尼爾·弗雷在評論中指出,該指令:

list<int> range(0, 100); 

將創建大小爲0的列表,它的元素(其元素)都用值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 
+2

單獨'mutable'不會解決問題,'strings'是一個數組。 – Praetorian 2013-03-19 20:20:49

+0

@Praetorian:它似乎編譯[here](http://liveworkspace.org/code/yJL1f$27)雖然... – 2013-03-19 20:21:38

+0

地球上的數組是如何可複製的?也許捕獲的值是在數組之後指向隱式轉換?另外,從VS2012 *錯誤C3478:'strings':數組不能被俘獲*。但是LWS上的所有2個編譯器都會編譯它。 – Praetorian 2013-03-19 20:23:15

1

這種變化應修復它,所以你通過引用捕獲:

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

而且丹尼爾和安迪指出你的range初始化可能不是你所期望的,因爲它創建了一個zero大小的列表:

list<int> range(0, 100);