2013年2月26日火曜日

C++におけるtemplateキーワードの効果の忘却とついでにtypenameについて

templateキーワードのこの用法、
半日もこの使い方を本当にまるですっかり思い出せずに浪費してしまいました。

ずっとg++-4.7.2であれでもないこれでもないと悩んで、気紛れにテストコードをclang++-3.1に翻訳させてみたなら、
a.cxx:104:47: error: use 'template' keyword to treat 'offset_of' as a dependent template name
こんなエラーメッセージ。

最初はチラミでtemplateの明示的なインスタンス化を適切な場所に書けとかそういう事だろうかと思ったものの、読んで「まてよ…まてよ…これは…そうか!!」と思い出した始末。

これは先にポストしたvertex型を実際にlibWRP-GLEWに組み入れて実用化しようと試みている最中に遭遇して、そのまま夕方から日付が変わる頃までこのtemplateキーワードの用法を思い出せずに悩んだ。

具体的には、特定のvertex型A型引数で受け取り保持しているテンプレートクラスBがあった時、つまりB<A>なるクラスが定義された時、このB<A>の内部に定義した関数では
typename A::offset_of<0>::type
の様Aの内部でpublicに定義されたテンプレート型利用できない(g++-4.7.2曰くNot foundエラー)

これを意図通り利用する為には、
typename A::template offset_of<0>::type
templateキーワードを適切に挿入すれば良い( ´∀`)

ちなみにこれ、Bの内部でAを使うのではなく、上の状況の発生する位置でAと全く同じ型を直接定義するなりusingするなりすれば、そちらを介してはtemplateキーワード無しで意図通りに翻訳できるし、もちろんそれは同様にBとは無関係なB<A>やAを定義しているスコープでもtemplateキーワード無しで意図通りに翻訳できるので状況を把握するまで紛らわしい。

と、言うか実際れていてこの用法とその必要性を思い出すまでに半日も掛かってしまった。

そんな次第でもう忘れたく無いのでtemplateキーワードの用法を自分でも整理して明示的に記録して置く事にしました。

  1. 定義に使うtemplateキーワード
    1. テンプレートクラス
    2. テンプレート関数
  2. テンプレートのインスタンスを使う時のtemplateキーワード
    1. ライブラリーの都合などで翻訳単位が異なる場合事前の明示的なインスタンス化
    2. 文脈で続く何かがテンプレートだとコンパイラーに明示する

今回すっかり忘却していた用法は2.2.。もう、忘れたくない(;´Д`)

さて、もののついで、似たような何かにtypenameがある。ちなみに先の2.2.のパターンでtypenameは使えない。

typename用法も大きく分けて2つ。

  1. テンプレート型仮引数を示すキーワード
  2. 文脈で続く何かが型名だとコンパイラーに明示する
typenameの1.は紛らわしい事にclassキーワードでもまったく同じ効果となる。(ちなみに私はこの用途では現在はclassを使っている。昔はtypenameと真面目に打っていたが、Bjarne先生が「typenameとか長ったらしくてclassって打てばいいじゃん」って著書で言ってたのでアホらしくなってclassに変えた。)


2.は::でネストした型名を記述する際にしばしば必要になる。これくらいよしなに判断しろよ…と思うことは多いけど(;´Д`)

もう、忘れたくないtemplateキーワードの用法、コンパイラーが文脈で判断できない何かをそれはテンプレートでござると明示してけつかつキーワード。もう、忘れたくない。

0 件のコメント:

コメントを投稿