Reading notes effective C + + Item 45 uses member function templates to accept "all compatible types"

Source: Internet
Author: User

The smart pointer behaves like a pointer, but does not provide added functionality. For example, Item 13 explains how to use the standard auto_ptr and tr1::shared_ptr pointers to automatically delete resources on the heap at the correct time. Iterators in STL containers are basically smart pointers: Of course, you can't use "+ +" to move the built-in pointer to a node in the list to the next node, but List::iterator can do so.

1. Problem analysis--how to implement implicit conversion of smart pointers

One thing that a real pointer can do is to support implicit conversions. A derived class pointer can be implicitly converted to a base-class pointer, and a pointer to a non-const can be implicitly converted to a pointer to a const object, and so on. For example, consider transformations that can occur in a three-tier inheritance system:

1 classTop {...};2 classMiddle: PublicTop {...};3 classBottom: PublicMiddle {...};4Top *PT1 =NewMiddle;//Convert middle*⇒top*5 6Top *pt2 =NewBottom;//Convert bottom*⇒top*7 8 ConstTop *pct2 = pt1;//Convert Top*⇒const top*

It is tricky to imitate this transformation in user-defined smart pointers. We want the following code to compile:

1Template<typename t>2 classSmartptr {3  Public://Smart pointers is typically4 ExplicitSmartptr (T *realptr);//initialized by built-in pointers5 ...6 };7smartptr<top> pt1 =//Convert smartptr<middle>⇒8Smartptr<middle> (NewMiddle);//smartptr<top>9Smartptr<top> pt2 =//Convert smartptr<bottom>⇒TenSmartptr<bottom> (NewBottom);//smartptr<top> Onesmartptr<Consttop> pct2 = pt1;//Convert smartptr<top>⇒ A //Smartptr<const top>

There is no inherent relationship between different instances of the same template, so the compiler treats smartptr<middle> and smartptr<top> as completely different classes, and the relationship between them is no more than vector<float> and widgets come near. In order to achieve the conversion between the SMARTPTR classes, we must display the implementation.

In the smart pointer example code above, each statement creates a new smart pointer object, so now we focus on how to implement a smart pointer constructor that behaves as we wish. The key point is that there is no way to implement all the constructors we need. In the above inheritance system, we can construct a smartptr<top> with a smartptr<middle> or a smartptr<bottom>, but if the inheritance system expands in the future, The Smartptr<top> object must be able to be constructed from other smart pointer types. For example, if we add the following class:

1 class  Public Bottom {...};

We will need to support the creation of the Smartptr<top> object with the Smartptr<belowbottom> object, and we certainly do not want to implement it by modifying the smartptr template.

2. Implicit conversion using the member function template--generalization copy constructor

In principle, there is no limit to the number of constructors we need. Since the template can be instantiated as an unlimited number of functions, it seems that we do not need a smartptr constructor, we need a constructor template. Such a template is an example of a member function template (member function templates) (also known as member templates)-a template that generates member functions for a class:

 1  template<typename t>2  Span style= "color: #0000ff;" >class   Smartptr { 3  public  :  4  Template<typename u> //  member template  5  smartptr (const  smartptr<u>& Other); //  for a" generalized  6  //  copy constructor"  8  9 }; 

This means that for each type T and each type U, a smartptr<t> can be created with smartptr<u>, because Smartptr<t> has a smartptr<u> The constructor as a parameter. A constructor like this--one object to create another object, two objects from the same template but they are different types (for example, using smartptr<u> to create smartptr<t>), which is often called generalized copy constructors (Generalized copy constructors).

2.1 Implicit conversions do not require explicit

The above generalization copy constructor is not declared as explicit. This has been carefully considered. Type conversions between built-in pointer types, such as conversions from derived classes to base-class pointers, are implicit and do not require cast, so it is reasonable for smart pointers to mimic this behavior. Omitting explicit on a templated constructor just does this.

2.2 Remove the template instantiation function that does not meet the requirements

The generalization copy constructor implemented for Smartptr provides more than we want. We want to create smartptr<top> with smartptr<bottom>, but we don't want to create smartptr<bottom> with smartptr<top>; Because this violates the meaning of the public inheritance (Item 32). We also do not want to create smartptr<int> with smartptr<double>, because there is no implicit conversion from double* to int*. Therefore, we have to remove this set of member functions generated by the member template.

Suppose Smartptr follows the design of Auto_ptr and Tr1::shared_ptr, and also provides a GET member function to return a copy of the built-in type pointer contained by the smart pointer object (Item 15), We can use the implementation of the constructor template to restrict some transformations:

1Template<typename t>2 classSmartptr {3  Public:4Template<typename u>5Smartptr (Constsmartptr<u>& other)//Initialize this held PTR6: Heldptr (Other.Get()) { ... }//With other ' s held ptr7t*Get()Const{returnheldptr;}8 ...9 Private://built-in pointer heldTenT *heldptr;//By the smartptr One}

We initialize a data member of type t* in smartptr<t> with a pointer of type u* contained in smartptr<u> in the member initialization list. This can only be compiled if you can implicitly convert from the u* pointer to the t* pointer, which is exactly what we need. The actual result is that smartptr<t> now has a generalized copy constructor that can be compiled only if the passed parameter is of a compatible type.

3. member function templates support for assignment

The use of member function templates is not limited to constructors. Another common role for them is support for assignments. For example, TR1 's shared_ptr (item 13) supports the construction of all compatible built-in pointers, which can be constructed using TR1::SHARED_PTR,AUTO_PTR and Tr1::weak_ptr (item 54), as well as the assignment. But tr1::weak_ptr exceptions. The following is an excerpt from the TR1 description of the TR1::SHARED_PTR implementation, you can see in the Declaration template parameters when it is inclined to use class instead of TypeName. (as described in Item 42, they have the same meaning in this context.) )

1template<classT>classshared_ptr {2  Public:3 4template<classY>//construct from5 6 Explicitshared_ptr (Y * p);//Any compatible7 8template<classY>//built-in pointer,9 Ten  Oneshared_ptr (shared_ptr<y>Const& R);//shared_ptr, Atemplate<classY>//weak_ptr, or -  - Explicitshared_ptr (weak_ptr<y>Const& R);//auto_ptr the  -template<classY> -  - Explicitshared_ptr (auto_ptr<y>&R);  +  -template<classY>//Assign from +shared_ptr&operator= (shared_ptr<y>Const& R);//Any compatible Atemplate<classY>//shared_ptr or atshared_ptr&operator= (auto_ptr<y>& R);//auto_ptr - ... -};

All of these constructors are explicit, except for the generalization copy constructor. This means that another type implicitly converted from one type of shared_ptr to shared_ptr is allowed, but implicit conversions of built-in type pointers and other smart pointer types to shared_ptr are forbidden. (The conversion shown is possible (for example, by using cast).) It is also interesting that the auto_ptr passed to the Tr1::shared_ptr constructor and the assignment operator are not declared as const, but the TR1::SHARED_PTR and TR1::WEAK_PTR are declared as const. This is because the auto_ptr was modified when it was copied (Item 13).

4. The member function template generates a default copy constructor

member function templates are good things, but they do not modify the basic rules of the language. Item 5 explains that two functions in the 4 member functions that the compiler automatically generates are copy constructors and copy assignment operators. Tr1::shared_ptr declares a generalization copy constructor, it is clear that if type T and type Y are the same, the generalization copy constructor is instantiated into a "normal" copy constructor. So does the compiler generate a copy constructor for Tr1::shared_ptr? Or when constructing another tr1::shared_ptr with the same type of tr1::shared_ptr, does the compiler instantiate a generalization copy constructor?

As I said, the member template has no rules to modify the language. "If you need a copy constructor and you don't declare it yourself, the compiler will generate a" this rule is also one of them. Declaring a generalization copy constructor (a member template) in a class does not prevent the compiler from generating their own copy constructors (non-template), so if you want to control all aspects of the copy constructor, you must declare both a generalization copy constructor and a " Normal "constructor. The same applies for assignments. Here is the definition of tr1::shared_ptr:

1template<classT>classshared_ptr {2  Public:3shared_ptr (shared_ptrConst& R);//copy Constructor4 5template<classY>//Generalized6 7  8 9shared_ptr (shared_ptr<y>Const& R);//copy ConstructorTen  Oneshared_ptr&operator= (shared_ptrConst& R);//Copy Assignment A  -template<classY>//Generalized -  the  -shared_ptr&operator= (shared_ptr<y>Const& R);//Copy Assignment - ... -};

5. Summary
    • Use the member function template to generate a function that accepts all compatible types.
    • If you declare member templates for generalized copy constructors and generalization assignment operators, you also need to declare generic copy constructors and copy assignment operators.

Reading notes effective C + + Item 45 uses member function templates to accept "all compatible types"

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.