Overview
:
Traits is a characteristic extraction technology
It is widely used in Generic Programming
, Often used to make different types can be used for the same operation
Or provide different types of implementation for different types
.traits often need to use three c in realization
basic characteristics
:
ENUMTYPEDEFTEMPLATE
(Partial
SPECIALIZATION
among them
:
ENUM is used to unify one of different types of changes in different types of changes
, It is in C
is often used to replace DEFINE in the class
You can call
Enum is Define in the class
;
TypedEf is used to define your form of support features of your template class.
Your template class must support a feature in some form.
Otherwise, the type extractor Traits will not work properly.
. See here you might think
It's too harsh.
?actually not
Do not support a certain feature itself is also a way of support.
(See example
2
We define two indicates
, __ xtrue_type and __xfalse_type
, Respectively, respectively, support and not supporting a feature
).
Template
(Partial
Specialization is used to provide the right or more appropriate version of a particular type
.
With the more simple technologies
We can use the characteristics defined in the traits extraction class
And provide different implementations according to different characteristics
You can define from the characteristics to extraction
, Reality to Traits, the actual use of Traits is TRAITS technology
But this definition makes traits look too complicated
I am more willing to limit the definition of traits to characteristics.
Because this definition makes traits more simple
More easier to understand
^ _ _ _
^.
Example
:
Mentioned above
Traits can be used to provide different implementations for different types
So following two examples to explain how to achieve this.
.
EXAMPLE
1
:
Assume that we need to design a certain type of class to all types
(Including ordinary
int
/
Long
..., provide a complicated type of CLONE method CCOMPLEXOBJECT
And derived by this class
) Function of operation Clone
,the following
, First consider the solution with OO method
See the condition in front
, The first to jump into your mind is Interface
PURE
Virtual function, etc.
For our own design CCOMPLEXOBJECT
,This is not a problem
,but
For basic data types
And there are complicated types that do not provide Clone methods?
(At this time you may think
, If you have this more easy
All classes are derived from Object by default
And Object has provided a default Clone method
,but
To make the class really support Clone
Always imports Cloneable
,and so
It is also not possible to avoid the trouble here.
).
Below is a possible solution
:
Template
<
Typename T
,
Bool isclonable
>
Class XContainer
{...
Void Clone
(T
* Pobj
) {
IF
(Isclonable
) {
POBJ
-> Clone
();
Else
{
// ... non-clonable algorithm ...
}}};
But as long as you test it
This code cannot be compiled
.Why is this so
?the reason is simple
: For non-Clonable classes or basic types that do not implement Clone methods
POBJ
-> CLONE This sentence is illegal
.
So how do you solve this problem?
? The above cannot tell us through the code.
To make our code to compile
Do not make POBJ in a non-Clonable class or basic type code
-> Clone
, That is, we need to provide different implementations for different types.
In order to achieve this
We can use in our template class
ENUM defines a trait
To mark whether the CLONABLE class is labeled
, Then introduce a traits extraction class Traits inside the original template class, using SPECILIZING for this class.
To provide different implementations based on different trait
Specific implementation as follows
:
#include
Using Namespace STD
;
Class CComplexObject
// a Demo Class
{
public
:
Void Clone
() {Cout
<<
"in clone"
<< ENDL
;}};
// Solving the problem of chosing method to call by Inner Traits Class
Template
<
Typename T
,
Bool isclonable
>
Class XContainer
{
public
:
ENUM
{Clonable
= Isclonable
}
Void Clone
(T
* Pobj
) {
Traits
> (). Clone (POBJ) } Template < Bool flag > Class traits {}; Template <> Class traits < True > { public : Void Clone (T * Pobj ) { cout << "Before CLONINABLE TYPE" << ENDL ; POBJ -> Clone (); cout << "after cloning clonable type" << ENDL ;}}; Template <> Class traits < False > { public : Void Clone (T * Pobj ) { cout << "CLONING NON Clonable Type" << ENDL ;}}; Void main () { int * P1 = 0 ; CComplexObject * P2 = 0 ; XContainer < int , False > N1 ; XContainer , True > N2 ; n1 .clone (p1 ); N2 .clone (p2 } Compilation and run The above program outputs the following results : Doing Something Non CloNable BEFORE DOING SOMETHING Clonable in Clone After Doing Something Clonable this means We successfully selected different operations based on the incoming ISCLONABLE template parameters. , In the case of guaranteeing the interface , Provide different types of implementation for different types . EXAMPLE 2 : We will make some restrictions on the examples. Suppose our Clone operation involves only basic types and CCOMPLEXOBJECT and their school So we can further give the following solution : #include Using Namespace STD ; Struct __Xtrue_type {}; // define two mark-type Struct __xfalse_type {}; Class CComplexObject // a demo class { public : Virtual Void Clone () {Cout << "in clone" << ENDL ;}}; Class CDeriveDcomplexObject : Public CComplexObject // a demo deth Class { public : Virtual Void Clone () {Cout << "in derived clone" << ENDL ;}}; // a general eDtion of traits Template < Typename T > Struct Traits { TYPEDEF __XFALSE_TYPE HAS_CLONE_METHOD ; // Trait 1: HAS Clone Method or Not? All Types Defaultly Has No Clone Method. } // Specialized EDTION for ComplexObject Template <> Struct Traits > { TYPEDEF __XTRUE_TYPE HAS_CLONE_METHOD }; Template < Typename T > Class XContainer { Template < TypeName Flag > Class IMPL {}; Template <> Class IMPL <__ xi_type > { public : Void Clone (T * Pobj ) { POBJ -> Clone ()}}; Template <> Class IMPL <__ xfalse_type > { public : Void Clone (T * Pobj ) {}}; public : Void Clone (T * Pobj ) { IMPL > :: HAS_CLONE_METHOD > (). Clone (POBJ) }}; Void main () { int * P1 = 0 ; CCOMPLEXOBJECT C2 ; CComplexObject * P2 = & C2 ; CDeriveDcomplexObject C3 ; CComplexObject * P3 = & C3 ; // You Must Point To a derived Object by a base-class pointer, // it's a little quin XContainer < int > N1 ; XContainer > N2 ; XContainer > N3 ; n1 .clone (p1 ); N2 .clone (p2 ); N3 .clone (P3 } right now All basic types and CCOMPLEXObject class can be used for XContainer. . Conclusion : See here You may say Thats, TRAITS , I thought it was a deep thing! In fact, the technology is like this. , Talking, it is very easy. How is the key to use them to actually , For actual designing / WeVELOPMENT service .after all In the field of IT It is no value that cannot be applied to actual technologies. .