可変長のデータに対して同一関数を適用したい。
いまだと可変長テンプレート引数を使うのかなと思って次のようにしてみた。
http://lnseab.hatenablog.jp/entry/2012/12/13/172753 のテンプレートパックの展開を参考にして次のようなものを書いた。
expand-variadic-templates.cpp
#include <iomanip>
#include <iostream>
#include <utility>
#include <cstdio>
// clang needs non-void type for template pack
template <typename T>
int log(T target) noexcept {
time_t const now = std::time(nullptr);
std::tm const * timeinfo = std::localtime(&now);
std::cout
<< std::setfill('0')
<< "["
<< timeinfo->tm_year + 1900
<< "/"
<< std::setw(2) << timeinfo->tm_mon + 1
<< "/"
<< std::setw(2) << timeinfo->tm_mday
<< " "
<< std::setw(2) << timeinfo->tm_hour
<< ":"
<< std::setw(2) << timeinfo->tm_min
<< ":"
<< std::setw(2) << timeinfo->tm_sec
<< "] "
<< target
<< std::endl;
return 0;
}
// clang consexpr needs a literal type for return value
template <typename ... Args>
inline constexpr int expand_variadic_templates(Args ... args) noexcept {
return 0;
}
// clang consexpr needs a literal type for return value
template <typename ... Args>
inline constexpr int log_all(Args ... args) noexcept {
return expand_variadic_templates(log(args)...);
}
int main(const int argc, const char* const argv[]) {
log_all(1, 0.2, "foo", true);
return 0;
}
gcc/clang で -Wunused-parameter コンパイラーオプションを指定していると expand_variadic_templates で使わない仮引数が生成されて警告が出てしまうのでそこだけ注意かな。
渡す値の型がすべて同じ場合、 http://cpplover.blogspot.jp/2010/03/variadic-templates.html で紹介されてる再帰の方法も使えるけどスマートではないね。
同じことを再帰で処理することもできる。コメントで指摘してくださった amate さんありがとうございます。あれ ? これでいいんじゃね ?
recursive-variadic-templates.cpp
inline constexpr int log_all() noexcept {
return 0;
}
template <typename T, typename ... Args>
inline void log_all(T target, Args ... rest) noexcept {
log(target);
log_all(rest...);
}
int main(const int argc, const char* const argv[]) {
log_all(1, 0.2, "foo", true);
return 0;
}