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