考慮一下你負責爲標準庫容器寫一個簡單的漂亮打印工具的情況。在頭pretty_print.hpp
聲明如下功能:正在使用'包裝包裝'被認爲是不好的做法/指示壞的設計?
// In pretty_print.hpp
template<typename T>
void pretty_print(std::ostream& os, std::vector<T> const& vec);
template<typename T>
void pretty_print(std::ostream& os, std::set<T> const& set);
template<typename T, typename U>
void pretty_print(std::ostream& os, std::map<T, U> const& map);
// etc.
然而,由於容器不能向前聲明,您必須#include
每個容器頭。因此,包括pretty_print.hpp
到你的庫的其他部分會(可能會導致相當多的代碼膨脹)。因此,爲了避免將這些依賴引入到其他編譯單元中,您會創建一大堆文件(我稱之爲'頭文件包裝器',因爲我找不到任何其他術語),稱爲print_vector.hpp
,print_set.hpp
等等有一個類似的佈局:
// In print_vector.hpp
#include <vector>
template<typename T>
void pretty_print(std::ostream& os, std::vector<T> const& vec);
// In print_set.hpp
#include <set>
template<typename T>
void pretty_print(std::ostream& os, std::set<T> const& set);
// you get the point
所以,當你想能夠pretty_print
一個向量,你會#include print_vector.hpp
,它將只介紹<vector>
到當前編譯單元,而不是<set>
,<map>
或者你mightn任何其他頭不需要。請注意,我使用的是pretty_print
作爲示例(我確信有很多優秀的方式可以打印容器),但還有其他一些原因可能需要執行此操作(例如,在製作lean_windows.h
標頭「包裝器」之前您需要#define WIN32_LEAN_AND_MEAN
包括windows.h
)。
我看不出這種方法有什麼問題,因爲這意味着您要避免導致可能無法在編譯單元中使用/需要的一堆頭文件引起的可能的膨脹。儘管如此,它仍然覺得「錯誤」,因爲它對別人可能並不明顯,你的'包裝器'實際上包含了你想要的標題,並且似乎玷污了包括標準庫標題的'神聖性'(#include <string>
是慣用的,而#include "string_wrapper.hpp"
不是)。
這是否被認爲是不良做法\表示設計不好?
在這個例子中,我不認爲你(或你的用戶)應想'print_vector.hpp'作爲對''包裝。碰巧,它確實包含'',但這不是*它的實際*,它用於聲明'pretty_print'的重載。如果有'''類似於'',那麼它會包括這個,相反,如果你想出了一個(不可移植的)方法來在特定的實現上向前聲明'vector',那麼你可以優化'print_vector'爲那個實現。一般用戶不應該依賴傳遞包含。 –
2013-02-13 12:08:24
包括''不會在程序中引入任何額外的代碼(「代碼膨脹」),它可能會增加編譯每個.cpp文件所需的時間。 –
2013-02-13 12:31:00
@SteveJessop:你對我的術語是正確的,也許我用過的例子並不是最好的。如果我包含一個包含一些編譯「選項」的大型庫頭文件(比如'windows.h'的'WIN32_LEAN_AND_MEAN'或'NOMINMAX'),那麼只包裝'#define's和'#include'就行了嗎?在頭文件中,只要它沒有用於暴露給用戶的文件中? @Bo:是的,你是對的。對於包含許多模板標題的後果,我不是百分之百的理解,但是從我讀過的內容的一般問題來看,我知道應儘可能避免這種情況。我想我有很多閱讀要做。 – 2013-02-13 12:43:33