Misunderstood C ++-templates and macros

Source: Internet
Author: User

Templates and macros
Some days ago, when the Forum was hitting a storm, someone came up with the conclusion that the template is essentially a macro. As a result, you have had a good debate. I originally wanted to join the debate, but I thought everyone's remarks had covered my ideas, so I did it.
Although I did not participate in the discussion, the question "What is the relationship between templates and Macros?" is always on my mind. Every time I relax, this problem quietly emerges. (Usually when you put your son down and take a hot bath comfortably :)).
After thinking for a long time, I decided to do some practical code to understand the differences between the two. Now, I will submit the test results to everyone and let everyone judge them.
There is no doubt that templates and macros are completely two things. Some functions of the template are not available in macros; some functions of macros are not available in the template. It is impossible to have the shadow of who is. What we want to know here is whether the nature of the template is macro.
It is necessary to clarify the meaning of the so-called "essence. Here I assume that one thing is the "essence" of another thing, and the latter is the subset of the former, or the latter is implemented directly or indirectly through the former, either the basic principle of the latter depends on the former. If anyone has doubts about this, we have to discuss it separately.
First, I wrote a template and tried to write a macro to implement the template function:
Template <typename T>
Class cls_tmpl
{
Public:
String F1 (){
Strings = V. F () + "1000 ";
Return S;
}
Void F2 (){
V. G ();
}
PRIVATE:
TV;
};
The following is Macro Simulation:
# Definecls_mcr (T )/
Class/
{/
Public :/
Void F1 (){/
V. F ();/
}/
Void F2 (){/
V. G ();/
}/
PRIVATE :/
TV ;/
}
When using a template, you need to write the following:
Cls_tmpl <TP1> CT;
Use the macro version to write:
Cls_mcr (TP1) cm;
The two are written in the same way. However, the following code is problematic:
Cls_tmpl <TP1> CT1;
Cls_tmpl <TP1> CT2;
CT1 = CT2; // OK, CT1 and CT2 are of the same type
Cls_mcr (TP1) cm1;
Cls_mcr (TP1) cm2;
Cm1 = cm2; // compilation error. The types of cm1 and cm2 are different.
Since cls_mcr (TP1) is expanded twice and each class is defined, the compiler will think that they are two different types. However, no matter how many times the template is instantiated, as long as the type parameters are the same, the template is of the same type.
These indicate that templates and macros have completely different semantics and cannot be directly implemented using macros. To avoid these problems, a two-phase operation is required:
Typedef cls_mcr (TP1) cls_mcr_tp1 _;
Cls_mcr_tp1_cm1;
Cls_mcr_tp1_cm2;
Cm1 = cm2; // The same type. values can be assigned.
This gives us a prompt, maybe the compiler can expand the macro on a "draft", and then use the expanded class name to all the cls_mcr (…) used (...) Replace. In this way, the template is implemented.
But things are not that simple. Consider the following code:
Class TP1
{
Public:
String F (){
Return "X ";
}
};

Cls_tmpl <TP1> CT1;
Ct1.f1 ();

Cls_mcr (TP1) cm1; // compilation error: TP1 does not contain the member function g ()
Cm1.f1 ();
Although the template and macro code are the same, the compiler provides different results. It goes back to the definition of cls_tmpl and cls_mcr. Both have a member function F2 () that accesses the member function g () of TP1 (). However, the template Code does not give any errors, but the macro has a compilation error. To clarify this difference, you must first understand a special mechanism of the C ++ template: the code in the template will be instantiated only when it is used. That is to say, when cls_tmpl <TP1> is encountered, the compiler does not completely expand the entire template class. Only when a member function in the template is accessed will the code of the member function be expanded for semantic check. Therefore, when I only call F1 (), no compilation error will be thrown. Compilation error occurs only when F2 () is called:
Ct1.f2 (); // compilation error. TP1 does not contain the member function g ()
This mechanism aims to reduce Compilation Time. But later it became a very important mechanism in generic programming and template metaprogramming. (For more information, see C ++ template. I also used this mechanism in my attempt to simulate attributes, which is very useful .)
On the contrary, macros directly expand all the code at the same time, and then perform a comprehensive language check during the compilation process, regardless of whether the member functions are used or not. At the beginning, the template only performs syntax check. Only the code used performs semantic check and actual compilation.
From this point, we can see that, even if the macro is allowed to be expanded in the "draft", there is also a huge difference in the way it is expanded with the template. With this alone, we can deny the conclusion that "the essence of a template is macro. However, if we look more relaxed, can we think this way: although the template and macro adopt a completely different expansion method, if every Member in the template is regarded as an independent macro, can a template be implemented through a set of macros instead of a macro?
Let's look at the member function F1 () of the template cls_tmpl <> ():
String F1 (){
Strings = V. F () + "1000 ";
Return S;
}
If we regard F1 as a macro, F1 will expand in the macro mode as needed, and then formally compile it. Of course, we must first convert the Template into a set of macros. If this is the case for a compiler, you can barely think that the compiler uses a macro to implement the template. (But can we still calculate macros like this ?)
However, when we think about another problem, it is no longer that simple. See the following code:
X = y;
A = B;
Assume that X, Y, A, and B are of the int type. After compilation, these two lines of code may become the following equivalent assembly code (actually a machine code ):
MoV eax, y
MoV X, eax
MoV eax, B
MoV A, eax
We can see that the two lines of code are converted into two assembly commands, respectively. The difference is that the involved memory variables. It can be considered that the compiler makes the assigned assembly code (machine code) into a "macro ":
# Define assign (V1, V2 )/
MoV eax, V2/
MoV V1, eax
Replace the macro parameter with the memory variable (Address) during compilation. In this case, should we consider the essence of the compiler (or compilation) as a macro?
Since the C ++ standard does not specify how to expand the template, it is difficult for us to know how various compilers implement the template, so we cannot know whether the template is implemented through macro physics. However, in my opinion, macros and templates are both syntax-level mechanisms. It would be too far-fetched to explain the (physical) nature of the template by using the syntax mechanisms such as macros.
I think the reasonable explanation is: if we need to put the macro and the template on what "Relatives", it is reasonable to say that the macro is the template's great cousin. The two are technically consistent. All are based on the replacement of identifiers. However, in terms of others, it is hard to say how much similarity or relationship they have. Macros are syntax-level mechanisms, while templates go deep into the semantic layer. There is nothing like syntax, semantics, and implementation.
The author of the saying "the nature of the template is macro" may be stroupstrup himself. Initially, he proposed that the template (called the type parameter at the time) can be implemented through macro. But soon afterwards, he found that the templates in his mind were quite different from macros. As a result, he and other C ++ creators have established and developed various templates.
This story should have ended, but it is widely spread. I guess there are two possible reasons. One is to make some beginners understand the basic features of the template, and use macros to explain the following templates in an approximate way, which makes it easy to understand. I once said to some unenlightened colleagues, "If you cannot figure out a template, you can understand it as a macro. But remember, it has nothing to do with macros !" Many people only listen to half a sentence. They remembered the first half of the sentence and threw away the more important one. So now I will never say this again.
Another reason is more sinister. Some people who try to suppress C ++ always spare no effort to degrade the various features of C ++. (we have to admit the C ++ problem, but we must be realistic ), especially those most powerful functions. Templates bear the brunt. Linking templates with Macro, the ugly and notorious "prehistoric fossil" can be of great help to combat the reputation of C ++. (Even the C ++ community actively rejects macros ).
In fact, whether the nature of a template is macro is of no practical significance. Even so, the value of the template will not be affected at all. Many advanced programming mechanisms are built on traditional technologies. For example, virtual functions are implemented by using function pointers and indirect calls. No one has ever said this.
However, many people have made a fuss about the template and want to demonstrate that the template is essentially backward. To deceive the world, especially those ignorant beginners. I wrote this article for the purpose of not being able to bear this kind of comments that refer to the deer as a horse.
On the other hand, by comparing the features of templates and macros, we can gain a deeper understanding of the features, capabilities, and limitations of the two mechanisms. There will always be new gains when you learn new things from a gentle understanding.

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.