Я буду честен с вами, я пишу код C++ 11 шаблонов для 4-х лет, и я до сих пор имеют проблемы с запоминанием, как соответствовать пустой аргумент пакет ...
этот маленький трик избегает рекурсивного расширения шаблона вообще: (EDIT: переписана для поддержки нулевых аргументов и автоматической вставки запятой разделителя)
#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
>
У вас есть три параметра и сбрить один в рекурсивном вызове. Почему вы ожидаете, что шаблон многопараметрических функций будет вызван только один раз? – Wintermute
после того, как напечатано 'apple, orange, mango' оно напечатано' ** End ** 'дважды, что меня смущает. В какое время 'std :: wcout <<" \ n ** End ** ";' вызывается дважды подряд. – Praveen