In a previous blog post, a similar topic was written. The following method is used.
TT& t){ ‘\n‘T...T... args){ ‘ ‘; logOld(args...);}
function calls have recursion, and templates can have recursion when they are expanded. In writing a recursive function, we need to find the exit of the recursion so that it does not fall into infinite recursion. Similarly, recursion also needs to consider recursive exits when using template expansion.
To achieve random log output, such as
Zz::logold (1 ); Zz::logold (1 , 2 ); Zz::logold (1 , 2 , Span class= "hljs-string" > '-' , "Today" ); int a [4] ; Zz::logold ( "Hello" , "world" , 2016 , '-' , 3 , , 19 , a);
The argument is not controllable, but in the recursive expansion, the last parameter is definitely the exit of recursion, as shown in the logOld function definition above. The effect of running:
However, this is a recursive implementation, the generated code is also nested, performance loss, but the reality is convenient and easy to understand.
Recently read some articles about variable parameter templates, there are some articles about the Parameter pack use of this Pack expansion .
>
Pack Expansio
A pattern followed by an ellipsis, in which the name of least one parameter pack appears at least once, is expanded int o zero or more comma-separated instantiations of the pattern, where the name of the parameter pack was replaced by each of The types from the pack, in order.
It is to provide a multi-parameter unpacking mode, the pattern must contain at least one parameter.
Based on this feature, I have designed the following code
template <typename T >typename std::d ecay<t > unpack (const t & T) {std::cout << t << "; TypeName std::d ecay<t > _ins; return _ins;} Template <typename t , TypeName ... Args>void Debuglogimpl (const t & T, const args& ... args) {std::cout << t << "; Auto _fun = [] ( ... ) {}; _fun (Unpack (args) ); Std::cout << \ n ' ;}
Unpack is a schema for unpacking a parameter,unpack (args) ... Describes multiple parameters.
For example, args is a,b,c, then unpack (args) ... Equivalent to unpack (a), unpack (b), unpack (c). This form of unpacking results, I now only think of as a function parameter. All I've defined is a lambda function that takes a multi-parameter and then calls this lambda function to invoke the unpack function collection after unpacking.
But the order of function parameters in the stack is from right to left, then the first call is unpack (c), the output is "C", then No. But in c++14, we can directly
...);
But in the c++11, this is not possible. I also didn't find a way to call the function after unpacking in this order. In order to solve the problem of the log is not smooth, but also wrote a large section of the special template.
Template<TypeNameT>TypeName STD::d ecay<t> Unpack (Constt& t) {STD::cout<< T <<"';TypeName STD::d ecay<t> _ins;return_ins;}Template<TypeNameTTypeName... Args>voidDebuglogimpl (Constt& T,Constargs&. args) {STD::cout<< T <<"';Auto_fun = [] (...) {}; _fun (Unpack (args) ...);STD::cout<<' \ n ';}Template<TypeNameT0>voidDebuglog (Constt0& t0) {Debuglogimpl (t0);}Template<TypeNameT0,TypeNameT1>voidDebuglog (Constt0& t0,Constt1& t1) {Debuglogimpl (t0, T1);}Template<TypeNameT0,TypeNameT1,TypeNameT2>voidDebuglog (Constt0& t0,Constt1& T1,Constt2& T2) {Debuglogimpl (t0, T2, T1);}Template<TypeNameT0,TypeNameT1,TypeNameT2,TypeNameT3>voidDebuglog (Constt0& t0,Constt1& T1,Constt2& T2,Constt3& T3) {Debuglogimpl (t0, T3, T2, T1);} ...Template<TypeNameT0,TypeNameT1,TypeNameT2,TypeNameT3,TypeNameT4,TypeNameT5,TypeNameT6,TypeNameT7,TypeNameT8,TypeNameT9>voidDebuglog (Constt0& t0,Constt1& T1,Constt2& T2,Constt3& T3,Constt4& T4,Constt5& T5,Constt6& T6,Constt7& T7,Constt8& T8,Constt9& T9) {Debuglogimpl (t0, T9, T8, T7, T6, T5, T4, T3, T2, T1);}
Adjust the parameters.
#define DEBUG_LOG(...) zz::debugLog(__VA_ARGS__)
Define a macro to unify the external caliber.
int main () {// ZZ:: Logold(1);// ZZ:: Logold(1,2);// ZZ:: Logold(1,2,'-',"Today");//int a[4];// ZZ:: Logold("Hello","World", .,'-',3,'-', +, a);Debug_log(1);Debug_log(1,2);Debug_log(1,2,3);Debug_log(1,'-',' A ',1,"Sssss");return 0;}
The results are as follows
Then there is
Tstd::decay<T>T& t){ std::cout‘ ‘; std::decay<T> _ins; return _ins;}
Why do you use decaythis way, if you don't have to
template <typename T>T unpack(const T& t){ std::cout‘ ‘; return t;}
For such a "Ssssss", it will be reported
/home/zhou/work/qt_project/zzLog/main.cpp:48functionfor‘unpack(const char [6])‘ _fun(unpack(args)...);---/home/zhou/work/qt_project/zzLog/main.cpp:36function returning an array ^
Use decay To resolve the problem by degrading the array const char* .
Using variable template parameters to implement the log function