std::void_t SFINAE (Substitution Failure Is Not An Error), its function is to select the correct template when we specialize the template to avoid failure
Reprinted C++ Template Advanced Guide
std::enable_if
boost::mpl boost metaprogramming library
1. Function template
Click to view the code
#include <iostream> template <typename T> T const & amp; Max(T const & amp; a, T const & amp; b) { return a > b ? a : b; } int main() { int a = 1; int b = 2; double c = 2.0; double d = 3.0; std::string s1 = "Hello"; std::string s2 = "World"; std::cout << "type:" << typeid(Max(a, b)).name() << "\tvalue:" << Max(a, b) << std:: endl; //type:int value:2 std::cout << "type:" << typeid(Max(c, d)).name() << "\tvalue:" << Max(c, d) << std:: endl; //type:double value:3 std::cout << "type:" << typeid(Max(s1, s2)).name() << "\tvalue:" << Max(s1, s2) << std:: endl; //type:class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> > value:World return 0; }
Second type template
Click to view the code
#include <iostream> #include <vector> template <typename T> classMyStack { private: std::vector<T> elements; public: void push(T const & amp;); void pop(); T top()const; }; template <typename T> void MyStack<T>::push(T const & amp; e) { elems.emplace_back(e); } template <typename T> void MyStack<T>::pop() { if (!elems.empty()) elems.pop_back(); else throw std::out_of_range("out_of_range"); } template <typename T> T MyStack<T>::top()const { if (elems.empty()) throw std::out_of_range("out_of_range"); return elements.back(); \t } int main() { try { MyStack<int> s1; s1.push(1); s1.push(2); s1.push(3); std::cout << s1.top() << std::endl; //3 s1.pop(); std::cout << s1.top() << std::endl; //2 MyStack<std::string> s2; s2.push("string1"); s2.push("string2"); s2.push("string3"); std::cout << s2.top() << std::endl; //string3 s2.pop(); std::cout << s2.top() << std::endl; //string2 s2.pop(); std::cout << s2.top() << std::endl; //string1 s2.pop(); s2.pop(); //There is no element on the top of the stack at this time, and an exception is thrown: out_of_range \t\t } catch (std::exception const & amp; e) { std::cout << e.what() << std::endl; } return 0; }
3. Keywords typename and class
template
is equivalent to template
More recommended:typename
Reprint template
and template
class
is used to define classes. After the template is introduced into C++, the initial method of defining the template is: template
Here the class
keyword indicates that T
is a type. Later, in order to avoid confusion caused by the use of class
in these two places, Therefore, the keyword typename
is introduced. Its function is the same as class
to indicate that the following symbol is a type. In this way, the following method can be used when defining a template: template
The keywords class
and typename
have exactly the same effect in the template definition syntax.
Does typename only work in template definitions? In fact, this is not the case. Another function of typename
is: Use nested dependent name (nested dependent name), as shown below:
class MyArray { public: typedef int LengthType; ..... } template<class T> void MyMethod( T myarr ) { typedef typename T::LengthType LengthType; //LengthType is equivalent to int LengthType length = myarr.GetLength; }
At this time, the role of typename
is to tell the C++ compiler that the string after typename
is a type name, not a member function or member variable. At this time, if there is no typename
, the compiler has no way to know whether T::LengthType
is a type or a member name (static data member or static function), so the compilation cannot pass.
Four. Template Instantiation
When we use a class template, the class template is instantiated only when the name of an instance of the class template is used in the code and the context requires that a class definition must exist.
-
Declaring pointers and references to a class template will not cause the class template to be instantiated because there is no need to know the definition of the class.
-
Defining an object of a class type requires the definition of the class, so the class template will be instantiated.
-
When using sizeof(), it calculates the size of the object and the compiler must instantiate it according to the type, so the class template is instantiated.
-
The new expression requires that the class template be instantiated.
-
Referencing members of a class template causes the class template to be instantiated by the compiler.
-
It should be noted that the member function of a class template is itself a template. Standard C++ requires that such a member function be instantiated only when is called or the address is taken. The type used to instantiate a member function is the type of the class object whose member function is to be called.
1. Display instantiation
When a template is explicitly instantiated, the compiler generates a template instance based on the type specified by the explicit instantiation before the template is used.
Explicit instantiation avoids certain overhead
2. Implicit instantiation
The compiler does not generate declarations and definition instances of the template before using it. Only when templates are used, the compiler generates instances of the corresponding type based on the template definition. Explicit instantiation requires only declaration and no redefinition. The compiler implements instance declarations and instance definitions based on templates.
Sample Code
Click to view the code
#include <iostream> template <typename T> void test(T val1, T val2) { std::cout << val1 + val2 << '\\ '; } template void test<float>(float val1, float val2); //Display instantiation int main() { test(1, 2);//Use implicit instantiation test(1.0f, 2.2f); return 0; }
Five. Template specializations and partial specializations
Parameter specification for a template is template specialization. Partial specialization refers to specifying some parameters, and full specialization refers to specifying all parameters. Template specializations must have a main template. Function templates cannot be partially specialized. std::enable_if, function template polymorphism
The order of calling priority from high to low is: full specialization > partial specialization > main template
Click to view the code
#include <iostream> template <typename T> struct Fun { using type = T; }; template <> // Template specialization, there must be a main template, otherwise the error message *** is not a template struct Fun<int> { using type = unsigned int; }; int main() { Fun<long>::type t = 10; Fun<int>::type t1 = 10; //Use specialized version return 0; }
6. Default template parameters
Click to view the code
#include <iostream> template <typename T = int> classMyClass { public: void display() { std::cout << typeid(T).name() << '\\ '; } }; template <typename T = float> void test() { std::cout << typeid(T).name() << '\\ '; } int main() { MyClass c1; //Initialize template parameters using the default type int c1.display(); MyClass<char> c2; c2.display(); test(); //Use default parameters test<char>(); return 0; }
Seven, C++20 Concepts
Template type constraints
Eight, std::iterator_traits
Can be used to obtain the type of the value pointed to by the pointer in the template.
Other
C++ template function unresolved external symbol
In a separated compilation environment, the compiler does not know the existence of another .cpp file when it compiles a .cpp file, nor does it look for it [it will look to the linker when it encounters a pending symbol]. This works fine without templates, but is dumbfounded when encountering templates, because templates are only instantiated when needed, so when the compiler only sees the declaration of the template, it cannot instantiate it. To instantiate this template, you can only create a symbol with external connections and hope that the connector can resolve the symbol’s address. However, when the template’s embodiment is not used in the .cpp file that implements the template, the compiler is too lazy to implement it. Therefore, a line of binary code for the template’s embodiment cannot be found in the .obj of the entire project, so the link The machine was also dumbfounded
Reprint C++ template summary