更多 C++ 習慣用法/物件生成器
外觀
簡化物件建立,無需顯式指定型別。(這不是工廠方法模式)
在 C++ 模板程式設計中,即使在小型程式中,物件的型別也會變得非常龐大且難以理解。例如,以下型別(Wrapper)是一個標準的一元函式物件,它封裝了類File中的成員函式read_line。
struct File
{
int read_line (std::string);
};
typedef std::mem_fun1_t<int, File, std::string> Wrapper;
使用for_each STL 演算法讀取一組檔案,在沒有物件生成器的情況下,看起來像這樣
void read_lines(std::vector<File *> files)
{
typedef std::mem_fun1_t<int, File, std::string> Wrapper;
std::string arg;
for_each(files.begin(), files.end(),
std::binder2nd<Wrapper>(Wrapper(&File::read_line), arg));
}
上面的程式碼幾乎不可讀,並且比必要的多餘。即使型別定義也不能提高可讀性,因為Wrapper之類的佔位符型別定義會分散注意力。物件生成器習慣用法可以緩解這種情況。
在物件生成器習慣用法中,會建立一個模板函式,它的唯一作用是從其引數構造一個新物件。它基於函式模板的一個有用屬性,而類模板沒有:函式模板的型別引數會從其實際引數自動推斷出來。例如,考慮 STL 中定義的一個簡單的物件生成器:make_pair。
template <class T, class U>
std::pair <T, U>
make_pair(T t, U u)
{
return std::pair <T, U> (t,u);
}
make_pair 返回pair 模板的一個例項,具體取決於make_pair 函式的實際引數。例如,make_pair(1, 1.0) 透過自動推斷傳遞給物件生成器函式的物件型別,建立一個型別為:std::pair<int, double> 的物件。make_pair 在生成的 pair 物件不需要儲存在區域性變數的情況下特別有用。
map <int, double> m;
m.insert (make_pair(1,1.0)); // No need to know how pair template is instantiated.
C++ 標準庫定義了幾個物件生成器,以避免程式碼膨脹。std::bind2nd 和 std::mem_fun 是兩個這樣的標準物件生成器,可用於避免在上面動機部分所示的示例中程式碼膨脹。
void read_lines(std::vector<File *> files)
{
std::string arg;
for_each(files.begin(), files.end(), bind2nd(mem_fun(&File::read_line), arg));
}
C++ 標準庫 (mem_fun、make_pair、bind1st、bind2nd 等)