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++ではデフォルトの引数を与えられる。


うぅん。まだまだ。

追記

だいぶ書き直した。

ま、だいぶ楽に書けるようになったのでオケー。