SFINAE template instantiation and specialization template and typename

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