[英]What are preprocessor macros good for?
閱讀另一個問題關於使用宏后,我在想: 它們是什么好?
我很快就會看到被其他語言構造取代的一件事是減少你需要在下面輸入的相關單詞的數量:
void log_type( const bool value ) { std::cout << "bool: " << value; }
void log_type( const int value ) { std::cout << "int: " << value; }
...
void log_type( const char value ) { std::cout << "char: " << value; }
void log_type( const double value ) { std::cout << "int: " << value; }
void log_type( const float value ) { std::cout << "float: " << value; }
而不是
#define LOGFN( T ) void log_type( const T value ) { std::cout << #T ## ": " << value; }
LOGFN( int )
LOGFN( bool )
...
LOGFN( char )
LOGFN( double )
LOGFN( float )
還有其他“不可替代的”嗎?
編輯:試圖總結原因 - 為什么在答案中遇到; 因為那是我感興趣的東西。主要是因為我有一種感覺,他們中的大部分是由於我們仍然在原始文本文件中編程,仍然是支持不佳的環境。
#ifdef DEBUG
,平台問題)(SadSido,Catalin,Goz) __LINE__, __TIME__
); 我也根據這個原因設置'字符串'(SadSido,Jla3ep,Jason S) require
與include
功能( #pragma once
)(SadSido,Catalin) MESSAGEMAP
, BOOST_FOREACH
)(SadSido,fnieto) #ifdef __DEBUG__
); #pragma once
); __FILE__
和__LINE__
- 由當前文件名和當前行替換; BEGIN_MESSAGE_MAP()
); 在這里看到有趣的宏觀討論:
最有用的 - 頭文件保護:
#ifndef MY_HEADER_GUARD
#define MY_HEADER_GUARD
// Header file content.
#endif
稍后添加[ 僅限Windows ]
將類導出到DLL:
#ifdef EXPORT_MY_LIB
#define MY_API __declspec( dllexport)
#else
#define MY_API __declspec( dllimport)
#endif
樣本類:
class MY_API MyClass { ... };
平台特定部分。
即
#ifdef WINDOWS
#include "WindowsImplementation.h"
#elif defined( LINUX )
#include "LinuxImplementation.h"
#else
#error Platform undefined.
#endif
我以前發過這個,但當然現在找不到了。 如果你想訪問__FILE__
和__LINE__
宏,那么另一個宏是目前最方便的方式 - 例如:
#define ATHROW(msg) \
{ \
std::ostringstream os; \
os << msg; \
throw ALib::Exception( os.str(), __LINE__, __FILE__ ); \
}
為了做一些像BOOST_FOREACH這樣的酷魔術技巧, 將變量注入一個范圍。
BOOST_FOREACH( char c, "Hello, world!" )
{
... use char variable c here ...
} // c's scope ends here
// if there's an outer c defined, its scope resumes here
因為不重復自己(DRY)的原因。 在編譯時涉及重復構造的事情,不能在其他方法(模板或你有什么)中抽象出來。 如果您發現重復相同的代碼構造20次,那么這是人為錯誤的潛在根源 - 希望可以使用模板將其抽象出去,但有時卻不會。 它總是在看到可以進行類型檢查和清晰審查的原始代碼的優勢與使用宏來實現任意替換模式(通常無法通過自動編程工具檢查)的優勢之間取得平衡。
字符串化和連接(#和##預處理器模式)不能由模板執行。
當然,在某些時候,您可能最好使用工具(無論是自定義還是現成的)來自動生成代碼。
現代語言采用的理念是需要一個支持處理器的語言功能缺失的標志,因此它們定義了預處理器在舊的K&R風格C中非常簡單地處理的各種語言功能。
例如,上面的代碼示例可以通過內聯函數進行簡化。
就個人而言,預處理器中最不可或缺的方面是清楚地表明某些事情是在源代碼中編譯完成的。 在編譯時消除死代碼路徑的java方法在讀取代碼時並不那么明顯。
他們的一個用途基本上是一個窮人(內聯)模板功能。
例如 :
#define MIN(X,Y) ((X) < (Y) ? : (X) : (Y))
這允許您為支持這些運算符的任何類型生成自定義MIN函數,這些函數在使用時實際上是內聯的。 當然沒有類型檢查,如果你沒有恰到好處的話,很容易就會出現奇怪的語法錯誤或不正確的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.