出力がめんどくさいので
※素人ががんばって気合で書いたコードと記事です。いじめないでね
2次元のDPで、デバッグ出力したいなーとなった時
としてしまいたい人や、
// C++
set<int> st = {3,1,4,1,5};
for(auto i=st.begin();i!=st.end();){//めんどい!!!
cout << *i << (++i==st.end()?"\n":" ");
}
みたいなのを書きたくない人のために、自分の書いたきたないコードを共有しておきます。
コード
// C++
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
return (os << p.first << " " << p.second);
}
template <class T>
ostream &ca(T b, T e, ostream &os, bool c) {
for (; b != e;) {
os << *b << ((++b == e) ? "" : (c ? " " : "\n"));
}
return os;
}
struct _has_itr {
template <class T, class U = class T::iterator>
static auto c(T *) -> true_type;
template <class T>
static auto c(...) -> false_type;
};
template <class T>
struct has_itr : decltype(_has_itr::c<T>(nullptr)) {};
struct _has_inr {
template <class T, class U = class T::value_type, class V = class U::iterator>
static true_type c(T *);
template <class T, class U = class T::value_type>
static true_type c(decltype(U::first) *);
template <class>
static auto c(...) -> false_type;
};
template <class T>
struct has_inr : decltype(_has_inr::c<T>(nullptr)) {};
template <class T, enable_if_t<has_itr<T>::value && !is_same_v<T, string> &&
!has_inr<T>::value> * = nullptr>
ostream &operator<<(ostream &os, const T &t) {
return ca(ALL(t), os, 1);
}
template <class T, enable_if_t<has_itr<T>::value && !is_same_v<T, string> &&
has_inr<T>::value> * = nullptr>
ostream &operator<<(ostream &os, const T &t) {
return ca(ALL(t), os, 0);
}
私はこれをテンプレに入れてしまっているので、#include<bits/stdc++.h>とusing namespace std;は省略しています。いります。
使い方
自分のテンプレに置きます。以上です。
一応出力ですが、vector,setのように"内部でイテレータが定義されている"かつ"stringでない" ものであれば
cout << objで出力できます。
デバッグ目的の方が使うかも
簡単な解説
今回、SFINAEという仕様(?)を使って実装しています。
ざっくりいうと、型テンプレートを使用するときに条件を付けられるものです。(詳細な仕様は割愛します)
条件を付けないと、例えばcout<<(int型);としたときにもtemplate<class T>に当てはまってしまい、使用する関数が一意に定まらないためにCEとなってしまいます。
vector,set,mapなどのコンテナを出力する関数は
具体的には、イテレータを持っているかどうかで判別しています。また、ご存じの通りstring型はイテレータを持っているので、除外するようにしています。
以上です。