p691〜pまで

だいぶ間が開きましたが、続きのテンプレートの特殊化から。

テンプレートの特殊化

・テンプレートの特殊化とは型ごとにテンプレートの定義を変更すること。
・特殊化をすると完全に型が決まってしまうので、実装はヘッダファイルに記述することができない。
・簡単な特殊化の例。コード自体に意味はなし。

// 基本となるテンプレート
template <typename T>
class Hoge
{
pubic:
  static const char* hoge = "hoge"
};

// クラス宣言での特殊化
// Hoge<int>の特殊化
// 既存のHoge内のメンバ宣言は全て無視される
template<>
class Hoge<int>
{
public:
  static const char* hoge = "int";
};

// 実体定義での特殊化
// Hoge<char>の特殊化
// そのメンバのみが特殊化される
template<> const char* Hoge<char>::hoge = "char";

部分特殊化

・クラス宣言形式の特殊化では必ずしもすべてのテンプレート引数を特定する必要はない。これを部分特殊化と呼ぶ。

// こんな感じでintだけ特殊化みたいな
template <typename T>
class Hoge<T, int>{};

// テンプレート引数の型が同じ場合に特殊化とか
template <typename U>
class Hoge1<U, U>{};

// 一方がポインタとか
template <typename V>
class Hoge2<V, V*>{};

・pair構造体テンプレートを用いることで、テンプレート引数を増やすことができる。

template<typename T>
class Hoge
{
};

// Hogeテンプレートは1つまでの型しか許容していないが、pairを用いることで増やすことができる。
// 結局はpairで部分特殊化しただけ。
template<typename FIRST, typename SECOND>
class Hoge< pair<FIRST, SECOND> >
{
};

関数テンプレートの特殊化

・特殊化はできるが部分特殊化はオーバーロードがあるのでいらない(できない)。
・関数テンプレートをオーバーロードした場合、より具体的な方が呼ばれる。

汎整数昇格

・intより下の型(バイト数が少ない型?short, char, bool)が式中に現れた場合、その値はintかunsigned intに暗黙キャストされる。これを汎数昇格という。
・暗黙にキャストされたとしてもサイズはint, unsigned intの方が大きいため、汎整数昇格が行われる前後で値は変化しない。
・ただし、このような場合には注意が必要。

(unsigned short)0に~を作用させて0xFFFF(65535)にしようとすると、汎整数昇格が行われ、~(int)(unsigned short)0となり、0xFFFFFFFF(-1)となってしまう。
この場合でもunsigned short型の変数に結果を代入するとオーバーフローを起こし、結果的には0xFFFFが得られるが、十分に注意しなければならない。

これでテンプレートは終了。pairとか正直使い方よくわからなかったので、ちょうどいい勉強になったかも。でもテンプレートはやっぱり使いどころが難しい気がする。
久々に勉強しましたが、なかなか面白い。やっぱり続けないといけませんね。だが眠い・・・。