printfデバッグ環境づくり
とりあえずprintfデバッグをまともに出来るようにしていこう。
基本的にpだけ使えばなんでもできるようにしてみた。pは値を返すので、p(1) + p(2)とできる。いちいちcoutで次の行に書く必要は無いので結構便利。
ついでに配列をベクタに変換出来るように改造してっと。
#include <iostream> #include <string> #include <vector> using namespace std; #define times(bind, n) for (int bind = 0; bind < n; bind++) #define foreach(bind, item) \ for (typeof ((item).begin()) bind = (item).begin(), __ie = (item).end() ;\ bind != __ie ; \ bind++) namespace debug { /* list operator */ template <class T> ostream& list_stream(ostream& os, T list) { for (typename T::iterator i = list.begin(), ie = list.end(); i != ie;) { os << *i; // 再帰してるので循環してると泣ける。 if (++i != ie) // 先に進める os << " "; } return os; } template <class T> ostream& operator<<(ostream& os, vector<T> values) { os << "#("; list_stream(os, values); os << ")"; return os; } void newline() { cout << endl; } template <class T> T p(T value) { cout << value << endl; return value; } } using namespace debug; /* array -> vector */ template <class T, size_t N> vector<T> copy_to_vector(const T (&value) [N]) { return vector<T> (value, value + N); } #define define_vector(bind, value) \ vector<typeof (*value) > bind(value, value + sizeof (value) / sizeof (typeof (*value))); /* iota 系*/ #include <cmath> template <class T> int sign(T n) { return (n > 0) - (n < 0); } vector<int> iota(int n, const int start = 0, int step = 1) { vector<int> seq(n); for (int i = 0, value = start; i < n; i++, value += step) seq[i] = value; return seq; } vector<int> seq(int start, int end) { return iota(abs(end - start) + 1, start, sign(end - start)); } vector<int> seq(int start, int end, int step) { return iota(abs(end - start) / step + 1, start, step); } int main() { string h[] = {"Hello, ", "Template", "World!!"}; // 配列の初期化テスト vector<string> hoge = copy_to_vector(h); // ちょっと面倒なので、 define_vector(hello, h); // マクロで。 p(hello); // 表示 newline(); p(iota(10)); // iota cout << seq(1, 10) << endl; // オペレータ追加してみた return 0; }
だいぶ修正した。
ついでに
何かと便利なiota系も追加した。
- iota(5)でゼロから5個 (0 1 2 3 4)
- iota(5, 1)で1から5個 (1 2 3 4 5)
- iota(5, 1, 2)で1から奇数を5個 (1 3 5 7 9)
- seq(1, 5)で1から5まで (1 2 3 4 5)
- seq(1, 5, 2)で奇数を5まで (1 3 5)
色々メモ
- イテレータはリストほど柔軟ではない。一個前にしか進めない。
- テンプレートの型解決は<1, 2, 3>の順番で行われるので、順番を考慮すること。
- 型解決はまだ不明な点が残る。
- T型の宣言を書く時は
typename T::iterator it = ...
- 配列の長さを取る時は、
template <class T, size_t N> vector<T> copy_to_vector(T (&value) [N])
- ベクタの初期化は
vector<int> v(value, value + sizeof (value) / sizeof (int))
- オペレータの追加を覚えた。
- C++ではデフォルトの引数を与えられる。
うぅん。まだまだ。
追記
だいぶ書き直した。
ま、だいぶ楽に書けるようになったのでオケー。