Type? Traits type extraction
Can be implemented in compiler calculation, query, judgment transformation and selection
Used to reduce loop complexity
Basic type? Traits
1. Simple type "traits"
Wrap compiler constant as a type ﹣ traits --- integral ﹣ constant
There is a constant member variable value in the integrated constant, which can be obtained through the integrated constant:: value
template<typename Type> struct Test : std::integral_constant<int, 2> { }; int main() { std::cout << Test<int>::value << endl; }
2. Type "traits" of type judgment
There are many commonly used defined traits, which are derived from the integration_constant.
https://en.cppreference.com/w/cpp/types
- Used to check whether the template type is a certain type
- Determine whether the template type is the target type by whether STD:: is XXX:: value is true.
template<class T> struct is_integral; // Is? Integral is used to check whether T is an unsigned integer // If T is, then is_integral::value is true
#include <type_traits> int main() { cout << std::is_const<const int>::value << endl; // 1 cout << std::is_const<int*>::value << endl; // 0 }
3. Judge the relationship traits between the two types
- is_same
Only when the type is strictly the same can it be considered as the same type
template<class T, class U> struct is_same; cout << is_same<int, int>::value << endl; // 1 cout << is_same<int, char>::value << endl; // 0
- is_base_of
Determine whether it is an inheritance relationship at compile time
template<class Base, class Derived> struct is_same;
- is_convertible
Can the preceding template parameter type be converted to the following
template<class From, class To> struct is_convertible;
4. Type conversion traits
30: : type indicates the converted type
Modification of const add_const remove_const Reference to remove_reference add_lvalue_reference add_rvalue_reference Remove dimensions at the top of the array remove_extent Remove all dimensions of array remove_all_extents remove_pointer add_pointer Remove reference and cv character, add function pointer to function decay ....
conditional select type according to condition
If B is true, then conditional::type is T
template<bool B, class T, class F> struct conditional;
Result \ of get traits P98 of callable object return type
declval
result_of
Enable if: P100
enable_if
Variable parameter template
When declaring, class is followed by
template<class... T> void f(T... args) { cout << sizeof...(args) << endl; } f(); // 0 f(1, 2); // 2 f(1, 2.5, ""); // 3
Variable parameter template function
Expand parameter package:
1. Recursive function expansion
// Termination function void f() { cout << "end" << endl; } // Expand function, set header and remaining parameters template<class T, class... Args> void f(T head, Args... rest) { cout << "args:" << head << endl; f(rest...); // Call yourself recursively and terminate the function the last time } int main() { f(1, 2.5, "adda"); }
2. Expand P105 through type﹐traits
3. Comma expression and initialization list
Initialize list by:
template<class... Args> void expand(Args... args) { // Initialize a variable length array by initializing the list int arr[] = { args... }; // 1,2,3,4 } expand(1, 2, 3, 4);
Comma expression:
When initializing the array, the implementation operates on the parameters
// Functions that handle each parameter in a parameter package template<class T> void print(T args) { cout << args << endl; } template<class... Args> void expand(Args... args) { // At the same time of initialization, execute the print function to operate on each parameter int arr[] = { (print(args), args)... }; // You can also use initializer? List instead of arrays std::initializer_list<int>{ (print(args), args)...}; // Using anonymous functions instead of print functions // The () after the anonymous function represents the execution of lamdba expression with null parameter std::initializer_list<int>{ ([&](){ cout << args << endl; }(), args)...}; // It can also be transferred directly without saving parameter package print(args...); } expand(1, 2, 3, 4);
About comma expressions
// Execute expressions before commas in order // 1. a = b // 2. d = c d = ( a = b , c)
Variable parameter template class
1. Template recursion and specialization expansion
Generally, 2-3 classes need to be defined, including class declaration and specialized template class
The following example is used to calculate the byte sum of parameter types
// 1. Forward declaration that Sum is a variable parameter template class template<typename... Args> struct Sum; // 2. Definition of class, recursively calling itself template<typename First, typename... Rest> struct Sum<First, Rest...> { enum { value = Sum<First>::value + Sum<Rest...>::value }; }; // 3. Specialized template class, termination function. When there is only one parameter, value is the size of this type (just an example) // It can also be written when there are only 0 or 2 parameters template<typename Last> struct Sum<Last> { enum { value = sizeof(Last) }; }; cout << Sum<int, char, int>::value; // 9