網(wǎng)上有很多關(guān)于pos機設計模板,C++ 函數(shù)模板特化和類模板特化的知識,也有很多人為大家解答關(guān)于pos機設計模板的問題,今天pos機之家(www.rcqwhg.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
1、pos機設計模板
pos機設計模板
我們知道,一種數(shù)據(jù)類型總是對應一個特定的操作集,使用一個特定的運算符集合。當函數(shù)模板和類模板實例化時,模板定義的一系列操作并不一定適合所有的預定義類型。
1 函數(shù)模板特化 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.
當為給定類型實例化函數(shù)模板時,編譯器會制作模板化函數(shù)的副本,并用變量聲明中使用的實際類型替換模板類型參數(shù)。這意味著對于每個實例類型,特定函數(shù)將具有相同的實現(xiàn)細節(jié)(只是使用不同的類型)。雖然在大多數(shù)情況下,這正是您想要的,但偶爾也有一些情況下,實現(xiàn)與特定數(shù)據(jù)類型略有不同的模板化函數(shù)很有用。
Template specialization is one way to accomplish this.
模板專門化是實現(xià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:
現(xiàn)在,讓我們假設我們希望以科學記數(shù)法輸出雙精度值(并且只有雙精度值)。為此,我們可以使用函數(shù)模板特化(有時稱為完整或顯式函數(shù)模板特化)為類型double創(chuàng)建print()函數(shù)的專門化版本。這非常簡單:只需定義專門化函數(shù)(如果函數(shù)是成員函數(shù),則在類定義之外進行定義),將模板類型替換為要為其重新定義函數(shù)的特定類型。下面是專門用于doubles的print()函數(shù):
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.
當編譯器實例化Storage<double>::print()時,它將看到我們已經(jīng)顯式定義了該函數(shù),并且它將使用我們定義的函數(shù),而不是從通用模板類中打印出版本。
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 <>告訴編譯器這是一個模板函數(shù),但沒有模板參數(shù)(因為在本例中,我們顯式指定了所有類型)。某些編譯器可能允許您省略這一點,但包含它是正確的。
2 類模板特化 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ù)據(jù)類型編寫一個通用版本,并將其保留在該版本中--每個向量都可以用完全相同的方式實現(xiàn)。模板特化的思想是重寫默認模板實現(xiàn),以不同的方式處理特定類型。例如,雖然大多數(shù)向量可能實現(xiàn)為給定類型的數(shù)組,但您可能會決定保存一些內(nèi)存,并將布爾向量實現(xiàn)為整數(shù)向量,每個位對應于向量中的一個條目。所以你可能有兩個獨立的向量類。
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ù)系統(tǒng)將為每個布爾值類型使用16或32位,即使只需要一個位。因此,我們可以通過將數(shù)據(jù)表示為一個整數(shù)數(shù)組,手動操作其位,從而使布爾向量看起來有點不同。
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:
為此,我們?nèi)匀恍枰付ㄕ谑褂妙愃朴谀0宓膬?nèi)容,但這次模板參數(shù)列表將為空:
template <>
and the class name is followed by the specialized type: class className<type>. In this case, the template would look like this:
類名后面緊跟著專用類型: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類的專用版本具有與通用vector類不同的接口(公共方法集),這將是完全合理的——盡管它們都是向量模板,但它們不共享任何接口或代碼。
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.
值得指出的是,在這種情況下進行專門化的主要原因是為了實現(xiàn)更節(jié)省空間的實現(xiàn),但您可以考慮其他原因來說明這一點——例如,如果您想根據(jù)一個模板類的類型向其添加額外的方法,而不是向其他模板添加額外的方法。
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.
例如,您可能有一個double向量,其中一個方法返回每個元素的非整數(shù)部分,盡管在這種情況下您可能認為更喜歡繼承。沒有什么特別的理由可以阻止沒有這些額外特征的雙向量的存在。然而,如果您對這個問題有強烈的感覺并想阻止它,那么可以使用模板專門化來做到這一點。
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.
另一種可能需要專門化某些模板的情況是,如果您的模板類型依賴于某些行為,而這些行為沒有在要存儲在該模板中的類集合中實現(xiàn)。
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.
例如,如果您有一個模板化的sortedVector類型,需要定義>操作符,并且有一組由其他人編寫的類,其中不包含任何重載操作符,但包含一個用于比較的函數(shù),那么您可以專門化模板來分別處理這些類。
3 類模板偏特化 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.
模板偏特化源于與上述完全特化類似的動機。然而,這次不是為一個特定類型實現(xiàn)一個類,而是實現(xiàn)了一個仍然允許一些參數(shù)化的模板。也就是說,您編寫的模板專門針對一個功能,但仍然允許類用戶選擇其他功能作為模板的一部分。讓我們用一個例子來說明這一點。
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):
回到擴展向量概念的想法,這樣我們就可以有一個sortedVector,讓我們思考一下它的外觀:我們需要一種進行比較的方法。如果已經(jīng)實現(xiàn),我們可以直接使用大于號>,如果還沒有實現(xiàn),則可以特化。但現(xiàn)在讓我們假設我們希望在排序向量中有指向?qū)ο蟮闹羔?。我們可以根?jù)指針的值對它們進行排序,只需執(zhí)行標準>比較(我們將有一個從低到高排序的向量):
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:
現(xiàn)在,請注意,在上面的for循環(huán)中,我們對T類型的元素進行了直接比較。大多數(shù)情況下都可以,但按實際對象類型而不是指針地址排序可能更有意義。為此,我們需要編寫具有以下行的代碼:
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:
當然,對于任何非指針類型,這都是錯誤的。這里我們要做的是根據(jù)類型是指針還是非指針使用偏特化(您可能會有很多級別的指針,但我們會保持簡單)。要聲明處理任何指針類型的偏(部分)特化模板,我們將添加以下類聲明:
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.
這里有幾個語法點需要注意。首先,我們的模板參數(shù)列表仍然將T命名為參數(shù),但聲明現(xiàn)在在類名稱后有一個T*;這告訴編譯器將任何類型的指針與此模板匹配,而不是與更一般的模板匹配。第二點需要注意的是,T現(xiàn)在是所指的類型;它本身不是指針。
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時,T將引用int類型!如果您將其視為一種模式匹配形式,其中T與類型匹配,如果該類型后跟一個星號,那么這就有一定的意義。這確實意味著您在實現(xiàn)時必須更加小心:請注意,vec_data是一個T**,因為我們需要一個由指針組成的動態(tài)大小的數(shù)組。
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類型像這樣工作——畢竟,如果您將它們放在指針數(shù)組中,您希望它們按指針類型排序。但這樣做有一個實際原因:當您為對象數(shù)組分配內(nèi)存時,必須調(diào)用默認構(gòu)造函數(shù)來構(gòu)造每個對象。如果不存在默認構(gòu)造函數(shù)(例如,如果每個對象都需要創(chuàng)建一些數(shù)據(jù)),那么您就需要一個指向?qū)ο蟮闹羔樍斜?,但您可能希望它們的排序方式與實際對象本身的排序方式相同!
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:
順便注意,您還可以偏特化模板參數(shù)——例如,如果您有一個fixedVector類型,該類型允許類的用戶指定要存儲的類型和向量的長度(可能是為了避免動態(tài)內(nèi)存分配的開銷),那么它可能如下所示:
template <typename T, unsigned length>class fixedVector { ... };
Then you could partially specialize for booleans with the following syntax
然后可以使用以下語法部分專門化布爾值
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不再是模板參數(shù),所以它被排除在模板參數(shù)列表之外,只留下長度。還要注意,長度現(xiàn)在顯示為fixedVector名稱的一部分(不同于使用通用模板聲明時,在名稱后不指定任何內(nèi)容)。(順便說一句,看到一個非類型的模板參數(shù)不要感到驚訝:如果模板參數(shù)是整數(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.
最后一個實現(xiàn)細節(jié)是偏特化:如果存在完全泛型類型、一些部分特化甚至一些完全特化的組合,編譯器如何選擇要使用的特化?一般的經(jīng)驗法則是編譯器將選擇最具體的模板特化——最具體的模板特化是其模板參數(shù)將被其他模板聲明接受,但不會接受其他同名模板將接受的所有可能參數(shù)的模板特化。
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.
例如,如果您決定需要一個按內(nèi)存位置排序的sortedVector,則可以創(chuàng)建sortedVector的完全特化,如果您聲明了sortedVector,則編譯器將選擇該實現(xiàn),而不是指針的不太具體的偏特化。它是最專業(yè)化的,因為只有int*匹配完全特化,而不是任何其他指針類型,如double*,而int*當然可以是其他模板的參數(shù)。
ref
https://www.learncpp.com/cpp-tutorial/function-template-specialization/
https://www.cprogramming.com/tutorial/template_specialization.html
以上就是關(guān)于pos機設計模板,C++ 函數(shù)模板特化和類模板特化的知識,后面我們會繼續(xù)為大家整理關(guān)于pos機設計模板的知識,希望能夠幫助到大家!