#Boost# Boost 高階函數(shù)
—
C++標準的函數(shù)綁定
#include <iostream>
#include <vector>
#include <algorithm>
void print(int i)
{
std::cout << i << std::endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), print);
}
算法 std::for_each() 要求它的第三個參數(shù)是一個僅接受正好一個參數(shù)的函數(shù)或函數(shù)對象。 如果 std::for_each() 被執(zhí)行,指定容器中的所有元素 - 在上例中,這些元素的類型為int - 將按順序被傳入至 print() 函數(shù)。
std::bind1st
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class add
: public std::binary_function<int, int, void>
{
public:
void operator()(int i, int j) const
{
std::cout << i + j << std::endl;
}
};
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), std::bind1st(add(), 10));
}
add() 函數(shù)已被轉(zhuǎn)換為一個派生自 std::binary_function的函數(shù)對象。將值10加至容器 v 的每個元素之上,并使用標準輸出流顯示結(jié)果。
—
boost::bind 綁定函數(shù)與參數(shù)
#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
void add(int i, int j)
{
std::cout << i + j << std::endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1));
}
add() 這樣的函數(shù)不再需要為了要用于 std::for_each() 而轉(zhuǎn)換為函數(shù)對象。 使用 boost::bind(),這個函數(shù)可以忽略其第一個參數(shù)而使用。
因為 add() 函數(shù)要求兩個參數(shù),兩個參數(shù)都必須傳遞給 boost::bind()。 第一個參數(shù)是常數(shù)值10,而第二個參數(shù)則是一個怪異的_1。
_1 被稱為占位符(placeholder),定義于 Boost.Bind。 除了 _1,Boost.Bind還定義了 _2 和 _3。 通過使用這些占位符,boost::bind() 可以變?yōu)橐辉⒍蛉暮瘮?shù)。
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));
}
因為使用了兩個占位符 _1 和 _2,所以boost::bind() 定義了一個二元函數(shù)。 std::sort() 算法以容器v 的兩個元素來調(diào)用該函數(shù),并根據(jù)返回值來對容器進行排序。 基于 compare()函數(shù)的定義,容器將被按降序排列。
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::sort(v.begin(), v.end(), compare);
}
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
}
如果容器要按升序排列而又不能修改 compare() 函數(shù)的定義。該例子僅改變了占位符的順序:_2 被作為第一參數(shù)傳遞,而 _1 則被作為第二參數(shù)傳遞至 compare(),這樣即可改變排序的順序。
boost::ref 將函數(shù)對象改變?yōu)橐梅绞?/span>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
void add(int i, int j, std::ostream &os)
{
os << i + j << std::endl;
}
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1, boost::ref(std::cout)));
}
boost::bind() 的參數(shù)是以值方式傳遞的,所以std::cout 不能直接使用,否則該函數(shù)會試圖創(chuàng)建它的一份拷貝。通過使用模板函數(shù) boost::ref(),象std::cout 這樣的流就可以被以引用方式傳遞,也就可以成功編譯上面這個例子了。
—
boost::function
#include <boost/function.hpp>
#include <iostream>
#include <cstdlib>
#include <cstring>
int main()
{
boost::function<int (const char*)> f = std::atoi;
std::cout << f("1609") << std::endl;
f = std::strlen;
std::cout << f("1609") << std::endl;
}
boost::function 可以定義一個指針,指向具有特定簽名的函數(shù)。 以上例子定義了一個指針 f,它可以指向某個接受一個類型為 const char* 的參數(shù)且返回一個類型為 int 的值的函數(shù)。 定義完成后,匹配此簽名的函數(shù)均可賦值給這個指針。 這個例程就是先將 std::atoi() 賦值給 f,然后再將它重賦值為std::strlen()。
注意,給定的數(shù)據(jù)類型并不需要精確匹配:雖然 std::strlen() 是以std::size_t 作為返回類型的,但是它也可以被賦值給 f。
如果 f 未賦予一個函數(shù)而被調(diào)用,則會拋出一個 boost::bad_function_call 異常。
—
Boost.Lambda匿名函數(shù)
#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << "\n");
}
Boost.Lambda 提供了幾個結(jié)構(gòu)來定義匿名函數(shù)。 代碼就被置于執(zhí)行的地方,從而省去將它包裝為一個函數(shù)再進行相應的函數(shù)調(diào)用的這些開銷。 與原來的例子一樣,這個程序?qū)⑷萜?v 的所有元素寫出至標準輸出流。
與 Boost.Bind 相類似,Boost.Lambda也定義了三個占位符,名為 _1, _2 和 _3。 但與 Boost.Bind 不同的是,這些占位符是定義在單獨的名字空間的。
雖然 Boost.Lambda 非常強大,但也有一些缺點。 要在以上例子中插入換行的話,必須用 "\n" 來替代 std::endl 才能成功編譯。 因為一元 std::endl 模板函數(shù)所要求的類型不同于 lambda 函數(shù)std::cout << boost::lambda::_1 的函數(shù),所以在此不能使用它。
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/if.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(2);
std::for_each(v.begin(), v.end(),
boost::lambda::if_then(boost::lambda::_1 > 1,
std::cout << boost::lambda::_1 << "\n"));
}
boost::lambda::if_then() 模板函數(shù),它要求兩個參數(shù):第一個參數(shù)對條件求值 - 如果為真,則執(zhí)行第二個參數(shù)。
除了boost::lambda::if_then(),Boost.Lambda,還提供了boost::lambda::if_then_else()和 boost::lambda::if_then_else_return()模板函數(shù) - 它們都要求三個參數(shù)。 另外還提供了用于實現(xiàn)循環(huán)、轉(zhuǎn)型操作符,甚至是 throw - 允許 lambda 函數(shù)拋出異常 - 的模板函數(shù)。
