網(wǎng)上有很多關(guān)于pos機設計模板,C++ 函數模板特化和類(lèi)模板特化的知識,也有很多人為大家解答關(guān)于pos機設計模板的問(wèn)題,今天pos機之家(www.xjcwpx.cn)為大家整理了關(guān)于這方面的知識,讓我們一起來(lái)看下吧!
本文目錄一覽:
1、pos機設計模板
pos機設計模板
我們知道,一種數據類(lèi)型總是對應一個(gè)特定的操作集,使用一個(gè)特定的運算符集合。當函數模板和類(lèi)模板實(shí)例化時(shí),模板定義的一系列操作并不一定適合所有的預定義類(lèi)型。
1 函數模板特化 Function template specializationWhen instantiating a function template for a given type, the compiler stencils out a copy of the templated function and replaces the template type parameters with the actual types used in the variable declaration. This means a particular function will have the same implementation details for each instanced type (just using different types). While most of the time, this is exactly what you want, occasionally there are cases where it is useful to implement a templated function slightly different for a specific data type.
當為給定類(lèi)型實(shí)例化函數模板時(shí),編譯器會(huì )制作模板化函數的副本,并用變量聲明中使用的實(shí)際類(lèi)型替換模板類(lèi)型參數。這意味著(zhù)對于每個(gè)實(shí)例類(lèi)型,特定函數將具有相同的實(shí)現細節(只是使用不同的類(lèi)型)。雖然在大多數情況下,這正是您想要的,但偶爾也有一些情況下,實(shí)現與特定數據類(lèi)型略有不同的模板化函數很有用。
Template specialization is one way to accomplish this.
模板專(zhuān)門(mén)化是實(shí)現這一點(diǎn)的一種方法。
template <typename T>class Storage{private: T m_value {};public: Storage(T value) : m_value { value } { } void print() { std::cout << m_value << '\'; }};
Now, let’s say we want double values (and only double values) to output in scientific notation. To do so, we can use a function template specialization (sometimes called a full or explicit function template specialization) to create a specialized version of the print() function for type double. This is extremely simple: simply define the specialized function (if the function is a member function, do so outside of the class definition), replacing the template type with the specific type you wish to redefine the function for. Here is our specialized print() function for doubles:
現在,讓我們假設我們希望以科學(xué)記數法輸出雙精度值(并且只有雙精度值)。為此,我們可以使用函數模板特化(有時(shí)稱(chēng)為完整或顯式函數模板特化)為類(lèi)型double創(chuàng )建print()函數的專(zhuān)門(mén)化版本。這非常簡(jiǎn)單:只需定義專(zhuān)門(mén)化函數(如果函數是成員函數,則在類(lèi)定義之外進(jìn)行定義),將模板類(lèi)型替換為要為其重新定義函數的特定類(lèi)型。下面是專(zhuān)門(mén)用于doubles的print()函數:
template <>void Storage<double>::print(){ std::cout << std::scientific << m_value << '\';}
When the compiler goes to instantiate Storage<double>::print(), it will see we’ve already explicitly defined that function, and it will use the one we’ve defined instead of stenciling out a version from the generic templated class.
當編譯器實(shí)例化Storage<double>::print()時(shí),它將看到我們已經(jīng)顯式定義了該函數,并且它將使用我們定義的函數,而不是從通用模板類(lèi)中打印出版本。
The template <> tells the compiler that this is a template function, but that there are no template parameters (since in this case, we’re explicitly specifying all of the types). Some compilers may allow you to omit this, but it’s correct to include it.
template <>告訴編譯器這是一個(gè)模板函數,但沒(méi)有模板參數(因為在本例中,我們顯式指定了所有類(lèi)型)。某些編譯器可能允許您省略這一點(diǎn),但包含它是正確的。
2 類(lèi)模板特化 Class Template SpecializationIn many cases when working with templates, you'll write one generic version for all possible data types and leave it at that--every vector may be implemented in exactly the same way. The idea of template specialization is to override the default template implementation to handle a particular type in a different way.For instance, while most vectors might be implemented as arrays of the given type, you might decide to save some memory and implement vectors of bools as a vector of integers with each bit corresponding to one entry in the vector. So you might have two separate vector classes.
在許多情況下,在使用模板時(shí),您將為所有可能的數據類(lèi)型編寫(xiě)一個(gè)通用版本,并將其保留在該版本中--每個(gè)向量都可以用完全相同的方式實(shí)現。模板特化的思想是重寫(xiě)默認模板實(shí)現,以不同的方式處理特定類(lèi)型。例如,雖然大多數向量可能實(shí)現為給定類(lèi)型的數組,但您可能會(huì )決定保存一些內存,并將布爾向量實(shí)現為整數向量,每個(gè)位對應于向量中的一個(gè)條目。所以你可能有兩個(gè)獨立的向量類(lèi)。
template <typename T>class vector{ // accessor functions and so forthprivate: T* vec_data; // we'll store the data as block of dynamically allocated // memory int length; // number of elements used int vec_size; // actual size of vec_data};
But when it comes to bools, you might not really want to do this because most systems are going to use 16 or 32 bits for each boolean type even though all that's required is a single bit. So we might make our boolean vector look a little bit different by representing the data as an array of integers whose bits we manually manipulate.
但當涉及布爾值時(shí),您可能并不真正想要這樣做,因為大多數系統將為每個(gè)布爾值類(lèi)型使用16或32位,即使只需要一個(gè)位。因此,我們可以通過(guò)將數據表示為一個(gè)整數數組,手動(dòng)操作其位,從而使布爾向量看起來(lái)有點(diǎn)不同。
To do this, we still need to specify that we're working with something akin to a template, but this time the list of template parameters will be empty:
為此,我們仍然需要指定正在使用類(lèi)似于模板的內容,但這次模板參數列表將為空:
template <>
and the class name is followed by the specialized type: class className<type>. In this case, the template would look like this:
類(lèi)名后面緊跟著(zhù)專(zhuān)用類(lèi)型:class className<type>。在這種情況下,模板如下所示:
template <>class vector <bool>{ // interfaceprivate: unsigned int *vector_data; int length; int size;};
Note that it would be perfectly reasonable if the specialized version of the vector class had a different interface (set of public methods) than the generic vector class--although they're both vector templates, they don't share any interface or any code.
請注意,如果vector類(lèi)的專(zhuān)用版本具有與通用vector類(lèi)不同的接口(公共方法集),這將是完全合理的——盡管它們都是向量模板,但它們不共享任何接口或代碼。
It's worth pointing out that the salient reason for the specialization in this case was to allow for a more space-efficient implementation, but you could think of other reasons why this might come in handy--for instance, if you wanted to add extra methods to one templated class based on its type, but not to other templates.
值得指出的是,在這種情況下進(jìn)行專(zhuān)門(mén)化的主要原因是為了實(shí)現更節省空間的實(shí)現,但您可以考慮其他原因來(lái)說(shuō)明這一點(diǎn)——例如,如果您想根據一個(gè)模板類(lèi)的類(lèi)型向其添加額外的方法,而不是向其他模板添加額外的方法。
For instance, you might have a vector of doubles with a method that returns the non-integer component of each element although you might think prefer inheritance in this case. There isn't a particular reason to prevent the existence of a vector of doubles without those extra features. If, however, you felt strongly about the issue and wanted to prevent it, you could do so using template specialization.
例如,您可能有一個(gè)double向量,其中一個(gè)方法返回每個(gè)元素的非整數部分,盡管在這種情況下您可能認為更喜歡繼承。沒(méi)有什么特別的理由可以阻止沒(méi)有這些額外特征的雙向量的存在。然而,如果您對這個(gè)問(wèn)題有強烈的感覺(jué)并想阻止它,那么可以使用模板專(zhuān)門(mén)化來(lái)做到這一點(diǎn)。
Another time when you might want to specialize certain templates could be if you have a template type that relies on some behavior that was not implemented in a collection of classes you'd like to store in that template.
另一種可能需要專(zhuān)門(mén)化某些模板的情況是,如果您的模板類(lèi)型依賴(lài)于某些行為,而這些行為沒(méi)有在要存儲在該模板中的類(lèi)集合中實(shí)現。
For example, if you had a templated sortedVector type that required the > operator to be defined, and a set of classes written by someone else that didn't include any overloaded operators but did include a function for comparison, you might specialize your template to handle these classes separately.
例如,如果您有一個(gè)模板化的sortedVector類(lèi)型,需要定義>操作符,并且有一組由其他人編寫(xiě)的類(lèi),其中不包含任何重載操作符,但包含一個(gè)用于比較的函數,那么您可以專(zhuān)門(mén)化模板來(lái)分別處理這些類(lèi)。
3 類(lèi)模板偏特化 Class Template Partial SpecializationPartial template specialization stems from similar motives as full specialization as described above. This time, however, instead of implementing a class for one specific type, you end up implementing a template that still allows some parameterization. That is, you write a template that specializes on one feature but still lets the class user choose other features as part of the template. Let's make this more concrete with an example.
模板偏特化源于與上述完全特化類(lèi)似的動(dòng)機。然而,這次不是為一個(gè)特定類(lèi)型實(shí)現一個(gè)類(lèi),而是實(shí)現了一個(gè)仍然允許一些參數化的模板。也就是說(shuō),您編寫(xiě)的模板專(zhuān)門(mén)針對一個(gè)功能,但仍然允許類(lèi)用戶(hù)選擇其他功能作為模板的一部分。讓我們用一個(gè)例子來(lái)說(shuō)明這一點(diǎn)。
Going back to the idea of extending the concept of vectors so that we can have a sortedVector, let's think about how this might look: we'll need a way of making comparisons. Fine; we can just use > if it's been implemented, or specialize if it hasn't. But now let's say that we wanted to have pointers to objects in our sorted vector. We could sort them by the value of the pointers, just doing a standard > comparison (we'll have a vector sorted from low to high):
回到擴展向量概念的想法,這樣我們就可以有一個(gè)sortedVector,讓我們思考一下它的外觀(guān):我們需要一種進(jìn)行比較的方法。如果已經(jīng)實(shí)現,我們可以直接使用大于號>,如果還沒(méi)有實(shí)現,則可以特化。但現在讓我們假設我們希望在排序向量中有指向對象的指針。我們可以根據指針的值對它們進(jìn)行排序,只需執行標準>比較(我們將有一個(gè)從低到高排序的向量):
template <typename T>class sortedVector{public: void insert (T val) { if( length == vec_size ) // length is the number of elements { vec_size *= 2; // we'll just ignore overflow possibility! vec_data = new T[vec_size]; } ++length; // we are about to add an element // we'll start at the end, sliding elements back until we find the // place to insert the new element int pos; for( pos = length; pos > 0 && val > vec_data[pos - 1]; --pos ) { vec_data[pos] = vec_data[pos - 1]; } vec_data[pos] = val; } // other functions...private: T *vec_data; int length; int size;};
Now, notice that in the above for loop, we're making a direct comparison between elements of type T. That's OK for most things, but it would probably make more sense to have sorted on the actual object type instead of the pointer address. To do that, we'd need to write code that had this line:
現在,請注意,在上面的for循環(huán)中,我們對T類(lèi)型的元素進(jìn)行了直接比較。大多數情況下都可以,但按實(shí)際對象類(lèi)型而不是指針地址排序可能更有意義。為此,我們需要編寫(xiě)具有以下行的代碼:
for( pos = length; pos > 0 && *val > *vec_data[pos - 1]; --pos )
Of course, that would break for any non-pointer type. What we want to do here is use a partial specialization based on whether the type is a pointer or a non-pointer (you could get fancy and have multiple levels of pointers, but we'll stay simple).To declare a partially specialized template that handles any pointer types, we'd add this class declaration:
當然,對于任何非指針類(lèi)型,這都是錯誤的。這里我們要做的是根據類(lèi)型是指針還是非指針使用偏特化(您可能會(huì )有很多級別的指針,但我們會(huì )保持簡(jiǎn)單)。要聲明處理任何指針類(lèi)型的偏(部分)特化模板,我們將添加以下類(lèi)聲明:
template <typename T>class sortedVector<T *>{public:// same functions as before. Now the insert function looks like this: insert( T *val ) { if( length == vec_size ) // length is the number of elements { vec_size *= 2; // we'll just ignore overflow possibility! vec_data = new T[vec_size]; } ++length; // we are about to add an element // we'll start at the end, sliding elements back until we find the // place to insert the new element int pos; for( pos = length; pos > 0 && *val > *vec_data[pos - 1]; --pos ) { vec_data[pos] = vec_data[pos - 1]; } vec_data[pos] = val; }private: T** vec_data; int length; int size;};
There are a couple of syntax points to notice here. First, our template parameter list still names T as the parameter, but the declaration now has a T * after the name of the class; this tells the compiler to match a pointer of any type with this template instead of the more general template. The second thing to note is that T is now the type pointed to; it isnotitself a pointer.
這里有幾個(gè)語(yǔ)法點(diǎn)需要注意。首先,我們的模板參數列表仍然將T命名為參數,但聲明現在在類(lèi)名稱(chēng)后有一個(gè)T*;這告訴編譯器將任何類(lèi)型的指針與此模板匹配,而不是與更一般的模板匹配。第二點(diǎn)需要注意的是,T現在是所指的類(lèi)型;它本身不是指針。
For instance, when you declare a sortedVector<int *>, T will refer to the int type! This makes some sense if you think of it as a form of pattern matching where T matches the type if that type is followed by an asterisk. This does mean that you have to be a tad bit more careful in your implementation: note that vec_data is a T** because we need a dynamically sized array made up of pointers.
例如,當您聲明sortedVector時(shí),T將引用int類(lèi)型!如果您將其視為一種模式匹配形式,其中T與類(lèi)型匹配,如果該類(lèi)型后跟一個(gè)星號,那么這就有一定的意義。這確實(shí)意味著(zhù)您在實(shí)現時(shí)必須更加小心:請注意,vec_data是一個(gè)T**,因為我們需要一個(gè)由指針組成的動(dòng)態(tài)大小的數組。
You might wonder if you really want your sortedVector type to work like this--after all, if you're putting them in an array of pointers, you'd expect them to be sorted by pointer type. But there's a practical reason for doing this: when you allocate memory for an array of objects, the default constructor must be called to construct each object. If no default constructor exists (for instance, if every object needs some data to be created), you're stuck needing a list of pointers to objects, but you probably want them to be sorted the same way the actual objects themselves would be!
您可能想知道您是否真的希望sortedVector類(lèi)型像這樣工作——畢竟,如果您將它們放在指針數組中,您希望它們按指針類(lèi)型排序。但這樣做有一個(gè)實(shí)際原因:當您為對象數組分配內存時(shí),必須調用默認構造函數來(lái)構造每個(gè)對象。如果不存在默認構造函數(例如,如果每個(gè)對象都需要創(chuàng )建一些數據),那么您就需要一個(gè)指向對象的指針列表,但您可能希望它們的排序方式與實(shí)際對象本身的排序方式相同!
Note, by the way, that you can also partially specialize on template arguments--for instance, if you had a fixedVector type that allowed the user of the class to specify both a type to store and the length of the vector (possibly to avoid the cost of dynamic memory allocations), it might look something like this:
順便注意,您還可以偏特化模板參數——例如,如果您有一個(gè)fixedVector類(lèi)型,該類(lèi)型允許類(lèi)的用戶(hù)指定要存儲的類(lèi)型和向量的長(cháng)度(可能是為了避免動(dòng)態(tài)內存分配的開(kāi)銷(xiāo)),那么它可能如下所示:
template <typename T, unsigned length>class fixedVector { ... };
Then you could partially specialize for booleans with the following syntax
然后可以使用以下語(yǔ)法部分專(zhuān)門(mén)化布爾值
template <unsigned length>class fixedVector<bool, length> {...}
Note that since T is no longer a template parameter, it's left out of the template parameter list, leaving only length. Also note that length now shows up as part of fixedVector's name (unlike when you have a generic template declaration, where you specify nothing after the name). (By the way, don't be surprised to see a template parameter that's a non-type: it's perfectly valid, and sometimes useful, to have template arguments that are integer types such as unsigned.)
請注意,因為T(mén)不再是模板參數,所以它被排除在模板參數列表之外,只留下長(cháng)度。還要注意,長(cháng)度現在顯示為fixedVector名稱(chēng)的一部分(不同于使用通用模板聲明時(shí),在名稱(chēng)后不指定任何內容)。(順便說(shuō)一句,看到一個(gè)非類(lèi)型的模板參數不要感到驚訝:如果模板參數是整數類(lèi)型,例如無(wú)符號的,那么它是完全有效的,有時(shí)也是有用的。)
A final implementation detail comes up with partial specializations: how does the compiler pick which specialization to use if there are a combination of completely generic types, some partial specializations, and maybe even some full specializations? The general rule of thumb is that the compiler will pick the most specific template specialization--the most specific template specialization is the one whose template arguments would be accepted by the other template declarations, but which would not accept all possible arguments that other templates with the same name would accept.
最后一個(gè)實(shí)現細節是偏特化:如果存在完全泛型類(lèi)型、一些部分特化甚至一些完全特化的組合,編譯器如何選擇要使用的特化?一般的經(jīng)驗法則是編譯器將選擇最具體的模板特化——最具體的模板特化是其模板參數將被其他模板聲明接受,但不會(huì )接受其他同名模板將接受的所有可能參數的模板特化。
For instance, if you decided that you wanted a sortedVector<int *> that sorted by memory location, you could create a full specialization of sortedVector and if you declared a sortedVector<int *>, then the compiler would pick that implementation over the less-specific partial specialization for pointers. It's the most specialized since only an int * matches the full specialization, not any other pointer type such as a double *, whereas int * certainly could be a parameter to either of the other templates.
例如,如果您決定需要一個(gè)按內存位置排序的sortedVector,則可以創(chuàng )建sortedVector的完全特化,如果您聲明了sortedVector,則編譯器將選擇該實(shí)現,而不是指針的不太具體的偏特化。它是最專(zhuān)業(yè)化的,因為只有int*匹配完全特化,而不是任何其他指針類(lèi)型,如double*,而int*當然可以是其他模板的參數。
ref
https://www.learncpp.com/cpp-tutorial/function-template-specialization/
https://www.cprogramming.com/tutorial/template_specialization.html
以上就是關(guān)于pos機設計模板,C++ 函數模板特化和類(lèi)模板特化的知識,后面我們會(huì )繼續為大家整理關(guān)于pos機設計模板的知識,希望能夠幫助到大家!
