Boost Libraries: Foreach

BOOST_FOREACH 是甚麼?

在 C++ 中,寫一個 iterate 一整個 sequence 的迴圈是讓人厭煩的,我們可以用 iterators,但是需要寫很多照本宣科的程式碼。或是我們可以用 std::for_each() 演算法,但是其實它也沒有省下多少功夫。相對之下,像是 Perl 之類的語言提供了內建的 "foreach" 來自動建構這樣的程序。BOOST_FOREACH 就是這類程序的 C++ 版本。它會直接幫助我們 iterates 整個 seqeuce,讓我們不用跟 iterators 奮鬥。

BOOST_FOREACH 是為了簡單易用以及有效率而設計的,他不會做動態 allocation,沒有 virtual function calls 也不用任何的 function pointers。這讓它可以產生 near-optimal 的程式碼,BOOST_FOREACH 的效率通常只跟手寫的 loop 差了幾個百分比而已。儘管 BOOST_FOREACH 是一個 macro,他的表現相當的出色。它剛好 evaluate 他的 argument 一次,讓我們不會看到有預期之外的效果。

Hello, world!

下面是一個簡單的程式,它使用了 BOOST_FOREACH 來 iterate 一個 std::string 的內容。
#include <string>
#include <iostream>
#include <boost/foreach.hpp>

int main()
{
    std::string hello( "Hello, world!" );
    
    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }

    return 0;
}
程式會 output
Hello world!
支援的類型

BOOST_FOREACH 會 iterates seqeuces,不過甚麼才會真正的組成一個 sequence?BOOST_FOREACH 是建構在 Boost.Range 之上,所以它自然會支援那些 Boost.Range 可以辨認的類型。舉例來說,我們可以用:
    * STL containers
    * arrays
    * Null-terminated strings (char and wchar_t)
    * std::pair of iterators
範例

下面是幾個使用 BOOST_FOREACH 的範例: 在 STL container 做 iterate:
std::list list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}
在 array 上面做 iterate with covariance (就是說 iteration variable 跟 element 的型別不完全一致)
short array_short[] = {1,2,3};
BOOST_FOREACH( int i, array_short )
{
    // The short was implicitly converted to an int
}
在 loop 中使用 return, continue 以及 break
std::deque deque_int( /*...*/ );
int i = 0;
BOOST_FOREACH( i, deque_int )
{
    if( i == 0 ) return;
    if( i == 1 ) continue;
    if( i == 2 ) break;
}
透過 reference iterate 整個 sequence,並且做變更
short array_short[] = { 1, 2, 3 };
BOOST_FOREACH( short & i, array_short )
{
    ++i;
}
// array_short contains {2,3,4} here
利用巢狀 BOOST_FOREACH iterate 一個二維 vector
std::vector<std::vector<int> > matrix_int;
BOOST_FOREACH( std::vector<int> & row, matrix_int )
    BOOST_FOREACH( int & i, row )
        ++i;