今日息子がつかまり立ちをした、と妻からメールがきた。
最近時々四つん這いの様子がおかしいので近いとは思っていた。
四つん這いは膝と手のひらをつくのが普通だと思うが最近は膝をつかずに四つん這いになっていることがあり、あれ?これ立つんじゃね?と思っていた。
まだ8ヶ月にもなっていないので中々早い。
巷ではあまり早く歩くようになるとよくないと言われているようなので少し心配。
でもこういう赤ちゃん関係の話は本当なのかよくわからない話も多いのでさほど気にしてはいない。
医療関係者でも人によって全く違うことを言っていて、初めのころは少し混乱させられた(例えば赤ちゃんは泣くことが仕事だと言う人もいれば、泣くことは仕事ではないという人もいる)。
科学的根拠があまりなく、経験則でものを言っている人も多いような気がする。
色々と意見を聞いて自分が納得できることを受け入れればよいと思う。
//////////////////////////
C++のお話。
教科書とかを見るとテンプレートは型に依存しない汎用的な処理を記述できるとか書いてある。
面白いけれど僕の仕事には役に立ちそうにないな、と長いこと放置していた。
でも最近になって、自作した配列クラスが要素の型が違うだけ(intとかfloatとか)で要素に対する処理はほぼ同じであることに気がついた。
これまで次のような感じになっていた。
class Array_int
{
private:
int a[M][N];
public:
void Method(){...}
};
class Array_float
{
private:
float a[M][N];
public:
void Method(){...}
};
いや、実は気がついてはいて、どうにかできないかと考えてはいたのだが
よい案が浮かばず、他にすることもあるので放置していたのだった。
型を引数で指定できればいいのになあ、とか考えてみたりした。
文字列で"int"とか"float"とか与える方法も考えたが
どう考えても処理が煩雑になるしきれいに書けそうにない。
ふと最近テンプレートが使えるんじゃないか、と思い試してみたらうまくいった。
テンプレートってかなり汎用的な処理に適用するイメージがあったので、intとfloat程度しか対象として想定していない自分のクラスにテンプレートを適用するという発想がなかった。
このクラスを紹介したいのだが結構複雑なクラスなのでもう少し単純な例を紹介する。
みんな大好きオイラー法でdf/dx=fをf(0)=1の初期条件の元で解くプログラムを例にとる。
したいことは値の精度をfloatとdoubleで切り替えることだ。
#include <iostream>
template <class data_t> class Euler
{
private:
data_t x;
data_t dx;
data_t value;
public:
Euler(data_t dx);
void step();
};
template <class data_t> Euler<data_t>::Euler(data_t dx)
{
x = 0;
value = 1.0;
this->dx = dx;
}
template <class data_t> void Euler<data_t>::step()
{
std::cout << x << " " << value << std::endl;
value += value * dx;
x += dx;
}
int main()
{
Euler<float> euler(0.01);
for(int n=0;n<100;n++)
{
euler.step();
}
return 0;
}
上述のプログラムは単精度板。Euler<double>とすれば倍精度で計算できる。
テンプレートの面白いところは型に依存せず同様の処理を行えることだ。
例えば次のようなdoubleを拡張した自作クラスがあったとする。
class MyDouble
{
private:
double value;
public:
MyDouble(){}
MyDouble(double value)
{
this->value = value;
}
double GetVal() const
{
return this->value;
}
MyDouble& operator=(const double &value)
{
this->value = value;
return *this;
}
MyDouble operator+=(const MyDouble &obj)
{
this->value += obj.value;
return *this;
}
MyDouble operator*(const MyDouble &obj)
{
MyDouble md;
md.value = this->value * obj.value;
return md;
}
friend std::ostream &operator<<(std::ostream &os , const MyDouble &obj)
{
os << obj.value;
return os;
}
};
こいつに対してオイラー法を適用することも可能。
int main()
{
MyDouble md(0.01);
Euler<MyDouble> euler(md);
for(int n=0;n<100;n++)
{
euler.step();
}
return 0;
}
必要な演算子さえオーバーロードされていればよいのだ。
こういう精度の切り替えに使えるとなるといろんなところで使えそうだ。
例えばマイコンからPCでデータを受信する際、charで送られてくるかshortで
送られてくるかによって別個に関数やクラスを作る必要がなくなる。
テンプレート、いいやん。