Modern C++ variable length parameter template

1. Variable length parameter template definition

Since C++11, C++ began to support variable-length parameter templates, allowing any number and types of template parameters, and there is no need to fix the number of parameters when defining them. Its form is defined as follows:

template<typename... Ts> class Variadic;

Its template instantiation:

1. A template class with 0 parameters Variadic<> zero;

2. Multi-parameter template class Variadic<int, double, std::string, std::list<int>> sample;

You can also define a template class that requires at least one parameter, which is defined as follows:

template<typename T, typename... Args> class Variadic;

2. Characteristic identification of variable length parameters

1. Get the number of variable length parameters

Tools: sizeof...

#include <iostream>

using namespace std;

template<typename... Args>
void func(Args... args)
{
    cout << "the count of 'args': " << sizeof...(args) << endl;
}

int main(int agrc, char* argv[])
{
    func();
    func(1);
    func(1, 2);
    func(1, 2, 3);
    
    return 0;
}

Program stdout:

the count of 'args': 0
the count of 'args': 1
the count of 'args': 2
the count of 'args': 3

2. Unpack

    1. Recursive template function

     Continuously pass template parameters to the function recursively to achieve the purpose of recursively traversing all template parameters.

#include <iostream>

template<typename T0>
void my_printf(T0 value) 
{
    std::cout << value << std::endl;
}

template<typename T, typename... Ts>
void my_printf(T value, Ts... args) 
{
    std::cout << value << std::endl;
    my_printf(args...);
}

int main() 
{
    my_printf(1, 1000, "123", 1.123, "HahaahaH");
    return 0;
}

Program stdout:

1
1000
123
1.123
HahaahaH

   2. Variable parameter template expansion

    The recursive unpacking of template parameters is a bit cumbersome to write. C++17 began to support variable parameter template expansion. The implementation of the above example can be replaced with the following code:

template<typename T, typename... Ts>
void my_printf(T value, Ts... args) 
{
    std::cout << value << std::endl;
    if constexpr(sizeof...(args) > 1)
        my_printf(args...);
}

   3. Initialization list expansion

   Use the comma expression and the characteristics of std::initializer_list.

template<typename T, typename... Ts>
void my_printf(T value, Ts... args) 
{
    std::cout << value << std::endl;
    (void)std::initializer_list<T>{([&args]{
        std::cout << args << std::endl;
    }(), value)...};
}

   4. Folding expression

   C++17 began to support (in fact, the C++ compiler enhanced the ability to push variable parameter types). The following code implements the sum of n data:

#include <iostream>

template<typename ... T>
auto sum(T ... t) 
{
    return (t + ...);
}

int main() 
{
    std::cout << sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl;
    return 0;
}

   Find the average:

#include <iostream>

template<typename ... T>
auto average(T ... t) 
{
    return (t + ...)/sizeof...(t);
}

int main() 
{
    std::cout << average(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl;
    return 0;
}

 

Guess you like

Origin blog.csdn.net/xunye_dream/article/details/114761058