出力がめんどくさいので

※素人ががんばって気合で書いたコードと記事です。いじめないでね

2次元のDPで、デバッグ出力したいなーとなった時

ABC261-D(入力例1)

としてしまいたい人や、

// 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型はイテレータを持っているので、除外するようにしています。

以上です。

いいなと思ったら応援しよう!