//#45 Accept all compatible types using member function templates
{
/* 1: When you use a smart pointer, a problem occurs and it becomes impossible to assign a subclass's object to a pointer to the base class.
Because the smart pointer specifies the type of the base class, the object that is assigned to it is a subclass of it.
2: workaround, using the member function template, you can template the copy constructor and assignment operation separately: * /
Template<class t>
class Smartptr
{
public:
// in order to prevent any conversion from whatever type, you can use a get () function to prevent such a situation.
// This will only be converted if the pointer has an implicit conversion, otherwise it will be an error.
Template<class u>
Smartptr (const smartptr<u>& Other): Heldptr (Other.get ())
t* get ()const { return heldptr;}
Template<class u>
smartptr<t>&operator= (const smartptr<u>& Other)
{
Heldptr = Other.get ();
return *this;
}
};
/ * 3: You declare a generalization of copy constructors and assignment functions that do not prevent the compiler from generating the normal version of These two functions for you
So if you want to control what happens when you pass in the same type: that is, u equals T , you have to implement the normal version of the function yourself. */
}
//#46 define a non-member function for a template when a type conversion is required
{
///1: Consider implicit type conversions for non-member functions under #24 , and if you add the templatenow, it won't work, it looks like this :
Template<class t>
Const rational<t> operator* (const rational<t>& R1, const rational<t> & R2)
{ ...}
/* If you have a rational<int> type of RA anddo such an operation RA * 6, sorry, cannot be compiled
This is because the compiler can only find the left argument,Ra It is known to be rational<int> , but look at the right argument
int? No, there is no corresponding function.
2: So in order for the compiler to recognize it, you must declare the function as a friend function of the Rational class. This way the compiler finds
The first parameter, it is determined that the function is in the class of rational<int> , and then 6 of the int type is naturally implicitly
converted into type of rational<int>.
3: But this is still unable to link, because the linker only found the declaration of lack of knowledge of the definition, because we define a template function, unless you
then implement a operatorspecifically for the int type. But what is the point of this template?
So the simplest way is to implement the definition directly within the class.
4: implementing a definition within a class can cause a problem: implicit inline, if the operation is complex and can cause code bloat, you can only
choose to call an external function, because it is inline, so there is no efficiency problem, much better.
5: Take a look at the concrete implementation of it * *
Template<class t>
Const Rational<t> domultiply (const rational<t>& R1,const rational<t>& R2)
{ ...}
Template<class t>
Rational
{
...
friend Const rational<t>operator* (const rational<t>& R1,const rational<t> & R2)
{ return domultiply (R1,R2)}
}
//6:domultiply cannot be implicitly converted, but it does not require such a conversion because the friend function has passed the correct type.
}
#47 Please use traits classes expression type information
{
/ * C + + does not dynamically know the type of an iterator, so we need a clever trick, that is traits
For example, I want to invoke a different version of a function for one-way, two-way, random iterators, with the help of iterator_traits: * /
Template<class iterator>
void dosomething (Iterator iter)
{_dosomething (Iter,iterator_traits<iterator>::iterator_category ())}
// This allows you to determine the type of the iterator using the parameters passed in.
// Here is very brief, mainly this thing is not simple to describe, detailed content can refer to the STL source code Analysis.
}
#48 know the template meta-programming
{
// is a template meta-programming introduction, Want to know the best reading!!!
}
Effective C + + notes (45-48)