[[C++ Tips]] * typenameをつかうところ [#v957f07d] template<typename T> struct Point { typedef T value_type; T x,y; }; typedef Point<float> Pointf; float distance(const Pointf& a, const Pointf& b) { return std::sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } template <typename T> typename T::value_type distance(const T& a, const T& b) { return static_cast<typename T::value_type>( std::sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)) ); } *テンプレートのtypenameとclassの違い [#lb192236] - typenameとは 型なのか値なのか、曖昧なときに、明示的に型だということを教えてあげるとにきにつかう。 template <typename T> struct Hoge { typedef Hoho T::Hoho; // T:Hohoが値なのか型なのか不明 typedef Hoho typename T:Hoho; // T:Hohoが型だとうことを示す }; - templateパラメータのtypenameとclass -- templateのパラメータはtypenameとclass両方が利用できる。 template <typename T> struct hoge; // OK template <class T> struct hoge; // OK -- template template パラメータの場合 template < template <class T> class TT> struct hoge; // OK template < template <typename T> class TT> struct hoge; // OK template < template <typename T> typename TT> struct hoge; // NG エラー ** templateパラメータのtypenameとは [#ydd022f3] あらゆる型を想定している時に使う。型にはクラスは含まれるので、クラスでもイミディエートのintやfloatでも良い場合にtypenameを使う。 ** templateパラメータのclassとは [#q5407682] クラスを意味するときにつかう。シンプルなテンプレートパラメータの場合はintやfloatが来てもエラーにならないが、テンプレートパラメータを必要とするテンプレートクラスをパラメータとする場合、classでないとエラーになる。クラス以外の型を入れない場合は、あえてclassを使うという使い方もある。 *グローバル変数の初期化 [#q69b7be7] - C場合、グローバル領域の変数はすべてゼロクリアされていることが保証されている。 // グローバル領域はゼロクリア保証 int a; static int b; int c[10]; //プロシージャ内は、指定をしないと値は未定 hoge() { static int a; // staticはゼロクリア保証 int b; // 未定 int c[10]; // 未定 static int d[10]; // ゼロクリア int e[10] = {}; // ゼロクリア C++のみ int f[10] = {1}; // Cで可能。f[0]は1、f[1]~f[9]は常にゼロでクリアされる。 * 参照型のメンバをもつクラスのコンテナとソート [#j00f0661] #include "stdio.h" #include <list> #include <vector> #include <algorithm> #include <functional> // 参照を持つクラスのswap namespace { struct Hoge { int& instance_; Hoge(int& i) : instance_(i) {} Hoge(const Hoge& h) : instance_(h.instance_) {} #if 0 Hoge& operator = (Hoge h) { swap(h); return *this; } void swap(Hoge& h) { std::swap(h.instance_, instance_); // 参照のswapはできない } #endif bool operator < (const Hoge& h) const { return instance_ < h.instance_; } }; #if 0 inline void swap(Hoge& h1, Hoge& h2) { h1.swap(h2); } #endif // output用 void print(const Hoge& h) { printf("%d\n", h.instance_); } } int main(int argc, char* argv[]) { int i1 = 1; int i2 = 2; int i3 = 3; Hoge h1(i1), h2(i2), h3(i3); std::vector<Hoge> vectorhoge; // vectorhoge.push_back(h3); // operator =がないとvector::push_backはでき ない // vectorhoge.push_back(h2); // vectorhoge.push_back(h1); // std::back_inserter(vectorhoge) = h1; // std::sort(vectorhoge.begin(), vectorhoge.end()); // operator =がないと vector::push_backはできない std::list<Hoge> listhoge; listhoge.push_back(h3); listhoge.push_back(h2); listhoge.push_back(h1); std::back_inserter(listhoge) = h1; listhoge.sort(); std::for_each(listhoge.begin(), listhoge.end(), print); return 0; }