「More C++ Idioms/複文マクロ(Multi-statement Macro)」の版間の差分

削除された内容 追加された内容
編集の要約なし
編集の要約なし
1 行
=<center>Multi-statement Macro</center>=
=== Intent ===
To write a multi-statement (multi-line) macro.
 
=== Also Known As ===
 
=== Motivation ===
Sometimes it is useful to group two or more statements into a macro and call them like a function call. Usually, an inline function should be the first preference but things such as debug macros are almost invariably macros rather than function calls. Grouping multiple statments into one macro in a naive way could lead to compilation errors, which are not obvious at first look. For example,
 
<source lang="cpp">
#define MACRO(X,Y) { statement1; statement2; }
</source>
 
would fail in an if statement if a semi-colon is appended at the end.
 
<source lang="cpp">
if (cond)
MACRO(10,20); // Compiler error here because of the semi-colon.
else
statement3;
</source>
 
The above statement expands to
 
<source lang="cpp">
if (cond)
{ statement1; statement2; }; // Compiler error here because of the semi-colon.
else
statement3;
</source>
 
giving a compiler error. Therefore, people came up with a widely used idiom for multi-statement macros, which is based on a do-while loop.
 
=== Solution and Sample Code ===
Here is an example of the multi-statement macro idiom.
<source lang="cpp">
#define MACRO(arg1, arg2) do { \
/* declarations, if any */ \
statement1; \
statement2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
</source>
 
When the caller appends a semicolon, this expansion becomes a single statement regardless of the context. Optimizing compilers usually remove any dead tests, such as while(0). This idiom is not useful when macro is used as a parameter to a function call. Moreover, this idiom allows return statement.
 
<source lang="cpp">
func(MACRO(10,20)); // Syntax error here.
</source>
 
=== Known Uses ===
ACE_NEW_RETURN, ACE_NEW_NORETURN macros in Adaptive Communication Environement (ACE).
<source lang="cpp">
#define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \
if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
} while (0)
</source>
 
=== Related Idioms ===
 
=== References ===
* [http://c-faq.com/cpp/multistmt.html What's the best way to write a multi-statement macro?]