Rangeの内容を出力する
こんな感じで使います。
int main() { using namespace std; vector<vector<string>> v{{"abc", "def"}, {"ghi", "jkl"}}; cout << iorate::print(v); }
出力
{{abc,def},{ghi,jkl}}
実装
#include <iostream> #include <iterator> #include <type_traits> namespace iorate { template <class T> struct print_holder { print_holder(T const &v) : v_(v) {} T const &v_; }; template <class T> inline print_holder<T> print(T const &v) { return print_holder<T>(v); } template <class Char> struct print_traits; template <> struct print_traits<char> { static char const left_curly_bracket = '{'; static char const right_curly_bracket = '}'; static char const comma = ','; }; template <> struct print_traits<wchar_t> { static wchar_t const left_curly_bracket = L'{'; static wchar_t const right_curly_bracket = L'}'; static wchar_t const comma = L','; }; template <class Char, class CharTraits, class T> inline auto output(std::basic_ostream<Char, CharTraits> &os, print_holder<T> h, int) -> typename std::enable_if<!std::is_array<T>::value, decltype(os << h.v_)>::type { return os << h.v_; } template <class Char, class CharTraits, class T> inline std::basic_ostream<Char, CharTraits> & output(std::basic_ostream<Char, CharTraits> &os, print_holder<T> h, ...) { os << print_traits<Char>::left_curly_bracket; bool first = true; for (auto it = std::begin(h.v_); it != std::end(h.v_); ++it) { if (first) first = false; else os << print_traits<Char>::comma; os << print(*it); } os << print_traits<Char>::right_curly_bracket; return os; } template <class Char, class CharTraits, class T> inline std::basic_ostream<Char, CharTraits> & operator <<(std::basic_ostream<Char, CharTraits> &os, print_holder<T> h) { return output(os, h, 0); } }
SFINAEとオーバーロードの合わせ技で、
- operator << で出力可能で、かつ配列でない場合はそのまま出力
- それ以外の場合はrangeと見なし、それぞれの要素をprintに渡して再帰的に出力
するようにしています。