C + + macros

Source: Internet
Author: User

0.

#define MALLOC (n, type) \sizeof(type))

1. Macros can be defined like functions, such as:
#define MIN (x, y) (x<y?x:y)//In fact this macro has a bug
But in the actual use, only when writing min (), must be parentheses, Min will be as a macro expansion, otherwise do not do any processing.
2. If the macro requires parameters, you can not pass, the compiler will give you a warning (macro parameters are not enough), but this will result in an error. As depicted in C + + books
, the compiler (preprocessor) does not have enough syntax checking for macros, so more checking work is done by yourself.

3. A lot of programmers don't know # and # #
#符号把一个符号直接转换为字符串, for example:
#define STRING (x) #x
const char *STR = STRING (test_string); The content of STR is "test_string", which means that the symbol behind
Add double quotes directly.
# #符号会连接两个符号, resulting in new symbols (lexical hierarchies), such as:
#define SIGN (x) int_# #x
int sign (1); When the macro is expanded, it becomes: int int_1;

4. Parameter macros, this is cool, it allows you to define similar macros:
#define LOG (format, ...) printf (format, __va_args__)
LOG ("%s%d", str, count);
__VA_ARGS__ is a system-predefined macro that is automatically replaced with a parameter list.

5. What happens when a macro calls itself? For example:
#define TEST (x) (x + TEST (x))
TEST (1); What's going to happen? To prevent unrestricted recursive expansion, the syntax specifies that when a macro encounters itself, it stops expanding, which is
that when the test (1) is unfolded, a test is found in the unfolding process, and the test is used as a general symbol. TEST (1)
The result is expanded to: 1 + TEST (1).

6. Prescan of macro parameters,
When a macro parameter is placed in the macro body, the macro parameter is first expanded (with exceptions, see below). When the expanded macro parameter is placed in the macro body,
The preprocessor scans the newly expanded macro body for a second time and continues to expand. For example:
#define PARAM (x) x
#define ADDPARAM (x) int_# #x
PARAM (AddParam (1));
Because AddParam (1) is a macro parameter as a param, first expand the AddParam (1) to int_1, and then put Int_1 in Param.
The exception is that if you use # or # # for the macro parameter in the Param macro, the macro parameter is not expanded:
#define PARAM (x) #x
#define ADDPARAM (x) int_# #x
PARAM (AddParam (1)); will be expanded to "AddParam (1)".

With such a rule, you can create a very interesting technique: print out what a macro looks like when it is expanded so that you can analyze the code:
#define TO_STRING (x) to_string1 (x)
#define TO_STRING1 (x) #x
To_string first expands all x (if x is also a macro) and then passes the to_string1 to a string, and now you can:
const char *STR = to_string (PARAM (AddParam (1))); Go for a look at the PARAM unfold.

7. An important addition: as I said in the 1th, if a macro like a function does not appear in parentheses when it is used, then the preprocessor simply
Treat the macro as a generic symbol (that is, do not process).

Let's see how the Macros Help us generate code automatically. As I said, macros generate code at the symbol level. I'm analyzing the boost.function.
module, because it uses a large number of macros (macros nested, then nested), I don't see the code at all. Later found a small template library TTL, said the
is to develop some small components to replace some boost (this is a good reason, because boost is really too big). Similarly, the library contains a function library.
The function here is the functor I mentioned earlier. Ttl.function Library in order to automatically generate a lot of similar code, using a macro:

#define TTL_FUNC_BUILD_FUNCTOR_CALLER (n) \
template< TypeName R, Ttl_tparams (n) > \
struct functor_caller_base# #n \
///...
The ultimate goal of this macro is to automatically generate a lot of functor_caller_base templates by invoking a method similar to Ttl_func_build_functor_caller (1):
Template struct FUNCTOR_CALLER_BASE1
Template struct FUNCTOR_CALLER_BASE2
Template struct FUNCTOR_CALLER_BASE3
///...
So, the core part is the Ttl_tparams (n) macro, which shows what this macro ultimately produces:
TypeName T1
TypeName T1, TypeName T2
TypeName T1, TypeName T2, TypeName T3
///...
We might as well analyze the entire process of Ttl_tparams (n). Analysis macro main grasp I mentioned above some of the points can be. The following procedure I suggest you turn over the TTL code,
Related code files: function.hpp, macro_params.hpp, MACRO_REPEAT.HPP, MACRO_MISC.HPP, macro_counter.hpp.

So, here we go

The analysis process, layer by level analysis, expand layers, such as ttl_tparams (1):

#define TTL_TPARAMS (N) ttl_tparamsx (n,t)
= TTL_TPARAMSX (1, T)
#define TTL_TPARAMSX (n,t) ttl_repeat (n, Ttl_tparam, Ttl_tparam_end, T)
= Ttl_repeat (1, Ttl_tparam, Ttl_tparam_end, T)
#define Ttl_tparam (n,t) typename t# #n,
#define Ttl_tparam_end (n,t) TypeName t# #n
#define TTL_REPEAT (N, M, L, p) ttl_append (Ttl_repeat_, Ttl_dec (n)) (m,l,p) Ttl_append (ttl_last_repeat_,n) (l,p)
Note that Ttl_tparam, ttl_tparam_end although also two macros, they are as parameters of the Ttl_repeat macro, according to Prescan rules, it seems that the first
The two macros are expanded and passed to Ttl_repeat. However, as I mentioned earlier, the two macros are Function-like macro, which requires parentheses when used,
If there is no parentheses, it is not treated as a macro. Therefore, when you expand Ttl_repeat, you should:
= Ttl_append (Ttl_repeat_, Ttl_dec (1)) (ttl_tparam,ttl_tparam_end,t) Ttl_append (ttl_last_repeat_,1) (
TTL_TPARAM_END,T)
This macro body looks very complex, carefully analyzed, can be divided into two parts:
Ttl_append (Ttl_repeat_, Ttl_dec (1)) (ttl_tparam,ttl_tparam_end,t) and
Ttl_append (ttl_last_repeat_,1) (ttl_tparam_end,t)
Analyze the first Part first:
#define Ttl_append (x, y) ttl_append1 (Y ×)//expand X, Y, and then connect X, Y.
#define TTL_APPEND1 (x, y) x # # Y
#define TTL_DEC (N) ttl_append (TTL_CNTDEC_, N)
Based on the principle of the first expansion parameter, the TTL_DEC (1) will be expanded first.
= Ttl_append (ttl_cntdec_,1) = Ttl_cntdec_1
#define TTL_CNTDEC_1 0 Note that TTL_CNTDEC_ is not a macro, ttl_cntdec_1 is a macro.
= 0, which means that Ttl_dec (1) is eventually expanded to 0. Back to the Ttl_append section:
= Ttl_repeat_0 (ttl_tparam,ttl_tparam_end,t)
#define TTL_REPEAT_0 (M,L,P)
TTL_REPEAT_0 This macro is empty, then the first part of the above is ignored, and now only the second part is left:
Ttl_append (ttl_last_repeat_,1) (ttl_tparam_end,t)
= = Ttl_last_repeat_1 (ttl_tparam_end,t)//Ttl_append merge Ttl_last_repeat_ and 1
#define TTL_LAST_REPEAT_1 (M,p) m (1,p)
= Ttl_tparam_end (1, T)
#define Ttl_tparam_end (n,t) TypeName t# #n
= = TypeName T1 unfolded.

Although we analyze it, it's not what we want. We should get the author macros's programming idea from those macros. Use macros very well
It seems to be a bit of a artifice, but he does allow us to code more automatically.

C + + macros

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.