我正在使用Linux平臺上的C++元編程語言的解析器。現在,我需要爲解析器實現選項/長選項來提供一些附加功能。基本上,如果用戶傳入一些額外的選項,解析器需要在解析文本文件時存儲統計信息。C++選項/長選項實現
我可以想出兩種實現方法。一種方法是用戶全局存儲由用戶輸入的選項。另一種方法是創建一個單例類來存儲選項。所以我想知道是否有其他方法來實施它。什麼是最好/最推薦的實施方式?提前致謝。
問候,
K.Hein
我正在使用Linux平臺上的C++元編程語言的解析器。現在,我需要爲解析器實現選項/長選項來提供一些附加功能。基本上,如果用戶傳入一些額外的選項,解析器需要在解析文本文件時存儲統計信息。C++選項/長選項實現
我可以想出兩種實現方法。一種方法是用戶全局存儲由用戶輸入的選項。另一種方法是創建一個單例類來存儲選項。所以我想知道是否有其他方法來實施它。什麼是最好/最推薦的實施方式?提前致謝。
問候,
K.Hein
兩個全局和單身會使你的解析器痛苦的單元測試。要單元測試解析器的行爲與不同的選項,你的測試將需要修改全局。這種方法至少有兩個問題:全局和你的類沒有明確的關聯。除了檢查實現之外,讀者不能判斷在類中使用了哪些全局變量,以及它們如何影響行爲。這樣的全局變量不能是const的(因爲它們是在main中設置的)。所以你放棄了溝通和強制執行的能力,一旦創建解析器,選項的值就不能改變。
經典單例甚至比全局變差,因爲它使您無法替換實現並通常完全阻止測試。
一個不錯的方法是注入一個將選項存儲到解析器構造函數的const對象。但是不要在這個對象中放置命令行解析邏輯,否則你將無法在測試中方便地使用該對象。
嗨,簡,你能詳細介紹一下const對象的注入嗎?或者,如果你能指出一些參考教程/例子,那將會很棒。謝謝:) –
爲了擴大在揚的回答,你將有一個功能,如:
bool my_parser(const parser_options &options);
的parser_options
類型可以是一個簡單的結構,例如:
struct parser_options
{
FILE *source_file;
bool warnings_as_errors;
std::shared_ptr<error_handler> eh;
...
};
的error_handler
可以這樣定義:
struct error_handler
{
virtual void error(int code, const char *message) = 0;
virtual void warning(int code, const char *message) = 0;
virtual ~error_handler() {}
};
該程序然後會做一些喜歡的東西E:
int main(int argc, const char *argv)
{
parser_options options;
// process argc/argv options here, adding them to options, e.g.:
// case WARN_AS_ERROR: options.warnings_as_errors = true; break;
return my_parser(options, &error) ? ERROR_SUCCESS : ERROR_FAILURE;
}
這允許你編寫直接調用my_parser
測試,命令行的處理獨立地設置parser_options
,並允許不同的error_handler
被指定爲(例如一種將信息格式化爲機器可讀的形式)。
注意:這並不意味着是一個解析器的完美設計,它只是一個如何設計類似的例子。如果應用程序可以配置爲控制流水線(例如,不進行優化,打印內部AST,內部表示,彙編代碼,預處理器輸出),則此設計不是嚴格測試所必需的。但是,設計更靈活,因爲它允許不同的程序直接調用命令行程序(GUI應用程序/ IDE,靜態分析工具等)來使用它。
在解析器應用程序中涉及到相當多的類。那麼採用這種方法,我必須將選項明確地傳遞給應用程序中的每個類?這將需要一些努力來重構類。 –
您可以將選項傳遞給應用程序中的每個類,或者只能傳遞所需的內容(例如,代碼生成類不需要解析選項)。你可以用很多bool選項來使用bitflags。設計一個好的架構非常複雜。你可能會經歷幾次迭代才能正確。從葉類開始,爲它們添加測試並向上構建。這將需要時間,但將是值得的。你應該反覆地改進設計,專注於特定領域,利用你所寫的內容的經驗,不完善的工作或難以更新的內容。 – reece
由於配置元素無論如何都必須是解析器環境的全局配置元素,所以兩者都可以工作。我建議,除非你有可配置選項的功能集,否則維護一個簡單的id值容器。一旦你知道了某些選項會暴露出來,你可以用更快的方式替換它)保持簡單和開放式。直到那麼 – WhozCraig
你可以在boost :: program_options中看到實現。 – Torsten