C++11 (3 generic programming) - type{traits, variable parameter function template

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

  1. 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
  1. is_base_of
    Determine whether it is an inheritance relationship at compile time
template<class Base, class Derived>
struct is_same;
  1. 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

Inheritance method expanded P109

126 original articles published, praised 14, visited 50000+
Private letter follow

Keywords: REST

Added by wiggst3r on Tue, 04 Feb 2020 11:40:37 +0200