Repeat the old topic-C ++ template tricks and Techniques

Source: Internet
Author: User

The content involved in this article is no longer a new thing. For some triangle and all star users, this is just a little trick. I have picked a few tricks and explained them. There is no profound concept. As for the purpose of writing this, there is nothing to do with it.

1. Obtain the type of a pointer after one unreference.
The pointer obtains the type of the referenced object once it is unbound. We can get this type with special features.
Template
Struct rm_a_ptr
{
Typedef t value_type;
};

Template
Struct rm_a_ptr
{
Typedef t value_type;
};

Rm_a_ptr : Value_type I = 5;

Of course we can get to remove all PTR, just need to make this special change. We don't need to discuss it here.

2, static_if
Static_if is the condition control during the compilation period. In fact, the # ifxxx compilation Preprocessor is doing these things, but static_if also has an additional action to let the language type system also participate in the operation.

Template
Struct static_if
{
Typedef TrueType value_type;
};

Template
Struct static_if
{
Typedef falsetype value_type;
};

The first non-type template parameter is determined based on the template's special nature, and TrueType and falsetype are selected.

3. Determine whether the two types are the same.
C ++ provides function overloading. the compiler searches for optimal matching in a series of overloaded functions. This is the basic basis for implementing type judgment. Therefore, we need two functions to complete this matching.
Template Int match (t );
Template Char match (...);
Both functions can accept all types of parameters, but the first match can make it accept only the specified parameter type to see the following code.
Match (1 );
Pass To specify the template parameter T as int, then the first match parameter is int, and 1 is int, so the best match here is the first match instead of the second. Based on this, we can determine whether the two types are the same.

Template
Struct same_type
{
Enum {value = (sizeof (INT) = sizeof (match (U **) 0 )))};
};

Match (U **) 0) What happened?
We explicitly convert NULL pointer 0 to u ** and then match it with T. If u and T are of the same type, the type returned by match is int. If u and T are not of the same type, the second match is matched, and the return type is Char. Therefore, when we compare the sizeof (INT) value with sizeof match, we can use the matching result during the compilation period, and then store the value by the value in Enum.

Why not use match? (U () for matching? Because if the U family is born from t, it matches the first match. Although the relationship between U and T is a, it is better to regard them as not the same. Otherwise, you will be worried about the following example.
Class {};
Class B: public {};

Bool x = same_type: value;
If (x = same_type: Value) // always Else.

So why should we use two-dimensional pointers instead of comparing T * and u? The reason is actually the same as above.

4. Determine whether a type is a function type.
An array has a feature that the element type cannot be function type or void. The above method can be used to achieve this judgment.
Template Char match_func_type (T (*) [2]);
Template Int match_func_type (...);

You must specify the template parameters when using match_func_type.
Match_func_type (0 );
This will match the second match_func_type, because the template parameter we specified is a function type. From this we can see that the first match_func_type parameter will be a pointer to the function type array, obviously this is impossible, because there is no function type array. So the second match_func_type will be matched. Note: we also need to exclude the void type.

Template
Struct is_function_type
{
Enum {value = (same_type : Value = 0) & (sizeof (INT) = sizeof (match_func_type ) (0 ))};
};
The pseudo code of the expression here is
(F! = Void & match_func_type (...));

5. Determine whether a type is a function pointer.
With the above features, we can quickly implement this. You can determine whether the type after a resolution reference is a function type.

Template
Struct is_function_pointer
{
Enum {value = is_function_type : Value };
};

6. What do we get?
The entire article above demonstrates some of the functions of the C ++ template. T is not just a container. However, this does not seem to play any role in actual work, or it is just a trick to make the code more dazzling, or even a means to prove that you are better than others. Finally, I began to question whether the code was necessary.

7 ,! @ # $ % ^ & * () _ +
Loadlibrary + getprocaddress + freelibrary is an annoying thing. You must judge the handle every time you use it. Therefore, during a period of time, I will copy & Paste previous code to process this part, then, make a small modification. Finally, I found that copy & Paste is also an annoying thing, so I wrote a class to encapsulate this job.
Class shared_wrapper
{
Public:
Shared_wrapper (const char * filename );
~ Shared_wrapper ();
Bool empty ();
Void * symbols (const char * symbol );
PRIVATE:
Hmodule module _;
};

It is obvious that constructors and destructor are responsible for loadlibrary and freelibrary respectively. Empty () returns true, indicating that the specified dynamic library has been loaded successfully. Symbols returns the interface address. The definition is as follows:
Void * shared_wrapper: Symbols (const char * symbol)
{
If (empty ())
Throw my_excep ("shared_wrapper.symbols, empty shared library ");

If (0 = symbol)
Throw my_excep ("shared_wrapper.symbols, null symbol ");

Void * result =: getprocaddress (module _, symbol );
If (0 = Result)
{
STD: String what = "shared_wrapper.symbols, no symbol named ";
What + = symbol;
Throw my_excep (what. c_str ());
}

Return result;
}

Later, I felt that symbols returned a void. Why not let it return a function pointer that we can use directly? So I changed it to this.
Template
Funcptr symbols (const char * filename)
{
//...
Return (funcptr) result;
}

Later, during the encoding process, the following line of code was written.
Shared. Symbols ("Interface") (5 );
Later, the compilation error tells me that I returned a function. In this case, I realized that symbols should accept a function type, not just the function pointer type. In the end, symbols should return a function pointer, and the specified function type already provides sufficient type information. So I moved my hands and feet on symbols again.

The template parameters of symbols can be of the function type or function pointer type. Therefore, write a helper class template to calculate the function pointer type of the template parameters for later use.

Template
Struct make_func_ptr
{
Typedef typename rm_a_ptr : Value_type prototype;

Typedef typename static_if : Value_type;
};

Here, we can understand static_if as the following pseudo code
Prototype = typeof (* t );
If (prototype = function type)
Return & prototype;
Else
Return int;

Why is return Int? Just borrow it, as long as there is no return function pointer type, the following will see the function of return Int.

Template
Typename make_func_ptr : Value_type
Symbols (const char * filename)
{
Typedef typename make_func_ptr : Value_type fptr_type;
If (is_function_pointer : Value = 0)
Throw my_excep ("shared_wrapper.symbols, template Is not a function type or a function pointer type ");

//...
Return (fptr_type) result;
}

The above return Int Is Used in symbols. If return int is set to fptr_type, the following if will capture this error. This is the final form.

8. review these amazing tricks.
Isn't it flexible and powerful to use code to implement features not provided by some languages? Some people always say this is useless. Maybe they have not considered how to use it. Whether the application is proper or not all comes from understanding and understanding the problem. What are your points of view?

This article is transferred from
Http://topic.csdn.net/u/20071013/19/c157fda3-1e2d-4f04-9550-f7d7906dd5d1.html

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.