C 11递归变异模板
c++11 recursive variadic templates
我正在尝试了解递归变异模板的工作方式。
#include <iostream>
template<typename T>
static inline void WriteLog(T&& msg) {
std::wcout << std::forward<T>(msg);
}
template<typename T, typename... Ts>
static void WriteLog(T&& msg, Ts&&... Vals) {
WriteLog(std::forward<T>(msg));
WriteLog(std::forward<Ts>(Vals)...);
std::wcout << "n**End**";
}
int main() {
WriteLog("apple, ", "orange, ", "mango");
}
输出:
apple, orange, mango
**End**
**End**
我只期望一个**End**
。为什么打印两次?
呼叫树:
WriteLog("apple, ", "orange, ", "mango");
->WriteLog("apple, ");
-> std::wcout << "apple, ";
->WriteLog( "orange, ", "mango");
->WriteLog("orange, ");
-> std::wcout << "orange, ";
->WriteLog( "mango");
-> std::wcout << "mango";
->std::wcout << "n**End**";
->std::wcout << "n**End**";
完成WriteLog(std::forward<Ts>(Vals)...);
的递归调用时,它必须执行下一个语句。此功能称为两次(一次用于"apple"
,一次用于"orange"
),因此编写了"**End**"
的两个打印量。
"mango"
的最后一个递归电话直接到第一个过载,因为包装中只剩下一个参数。
**End**
是为
-
WriteLog("apple, ", "orange, ", "mango");
中的CC_8 -
WriteLog("orange, ", "mango");
(带有WriteLog(std::forward<Ts>(Vals)...);
)中的WriteLog("apple, ", "orange, ", "mango")
我会和你老实,我一直在编写C 11模板代码4年,而我仍然很难记住如何匹配空参数包...
这个小技巧完全避免了递归模板扩展:(编辑:重新编写以支持零参数和自动逗号分离器插入)
#include <iostream>
namespace detail {
struct writer
{
template<class T>
void operator()(const T& t) {
if (_first) {
_first = false;
}
else {
std::cout << ", ";
}
std::cout << t;
}
private:
bool _first = true;
};
// non-template overload to catch no-parameter case
void do_write(writer&&)
{
}
// general case. Note w is passed by r-value reference
// to allow the caller to construct it in-place
template<typename T, typename...Ts>
void do_write(writer&& w, const T& t, Ts&&...ts)
{
w(t);
do_write(std::forward<writer>(w), std::forward<Ts>(ts)...);
}
}
// method 1 - no recursion
template<typename... Ts>
void WriteLog1(Ts&&... Vals) {
// expand one call for each parameter
// use comma operator to ensure expression result is an int
detail::writer write;
using expander = int[];
expander { 0, (write(std::forward<Ts>(Vals)), 0)... };
// write the final linefeed
std::cout << std::endl;
}
// method 2 - recursion
template<typename...Ts>
void WriteLog2(Ts&&...ts)
{
detail::do_write(detail::writer(), std::forward<Ts>(ts)...);
std::cout << std::endl;
}
int main() {
WriteLog1("apple", "orange", "mango");
WriteLog1("apple", "orange");
WriteLog1("apple");
WriteLog1("apple", 1.0, "orange", 1L, "mango", 2.6f);
WriteLog1(); // test pathalogical case
WriteLog2("apple", "orange", "mango");
WriteLog2("apple", "orange");
WriteLog2("apple");
WriteLog2("apple", 1.0, "orange", 1L, "mango", 2.6f);
WriteLog2(); // test pathalogical case
return 0;
}
输出:
apple, orange, mango
apple, orange
apple
apple, 1, orange, 1, mango, 2.6
apple, orange, mango
apple, orange
apple
apple, 1, orange, 1, mango, 2.6
>
相关文章:
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 到连接组件算法的问题(递归)
- 如何使用递归打印修改后的星号三角形图案
- 使用递归模板动态分配的多维数组
- 如何制作递归编译时间变异结构模板
- C 11递归变异模板