<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>zakio.net</title>
        <link>http://zakio.net/blog/</link>
        <description>端くれエンジニアの憂鬱</description>
        <language>ja</language>
        <copyright>Copyright 2009</copyright>
        <lastBuildDate>Wed, 22 Jul 2009 11:10:55 +0900</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>法則に違反したっていいじゃない</title>
            <description>
                <![CDATA[<p>
オブジェクト指向プログラミングにおける有名な法則の一つに<a href="http://ja.wikipedia.org/wiki/%E3%83%87%E3%83%A1%E3%83%86%E3%83%AB%E3%81%AE%E6%B3%95%E5%89%87">デメテルの法則</a> (Law of Demeter, LoD) というものがある。これは、簡単に言えば「戻り値として返されたオブジェクトのメソッドを呼び出してはいけない」という法則であり、例えば次のようなコードを書くと、「それ、デメテルの法則に違反しているよ」などと言われたりするので注意が必要だ。
</p>

<pre><code>
<span class="synType">int</span> id = projects.Find(projectName).GetID(); <span class="synComment">// プロジェクト名から ID を取得</span>

</code></pre>

<p>
そして、このコードをデメテルの法則に違反しないように書き換えると、次のようになる。
</p>

<pre><code>
<span class="synType">int</span> id = projects.GetID(projectName); <span class="synComment">// プロジェクト名から ID を取得</span>

</code></pre>

<p>
変更後のコードは Find が返すオブジェクト（ここでは多分 Project みたいなクラス）に依存していないので、オブジェクト間の結合度が下がったことになる。結合度の低いプログラムは良いプログラムであり、デメテルの法則に従えば良いプログラムになるというわけだ。
</p>

<p>
でも、ちょっと待って欲しい。
</p>]]>
                <![CDATA[<p>
様々な Project を一括して管理する Projects クラスがあったとして、その Projects を扱うようなプログラムが Project に依存するのは自然な流れだと思う。また、その方がコードがスッキリする場合だってあるはずだ。
</p>

<p>
例えば、Project クラスに次のようなメンバ関数が含まれていたとする。
</p>

<pre><code>
<span class="synType">class</span> Project {
<span class="synStatement">public</span>:
  <span class="synType">const</span> std::string&amp; GetName() <span class="synType">const</span>; <span class="synComment">// プロジェクト名</span>
  <span class="synType">int</span> GetID() <span class="synType">const</span>; <span class="synComment">// ID</span>
  <span class="synType">const</span> std::string&amp; GetDescription() <span class="synType">const</span>; <span class="synComment">// プロジェクトの説明</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
先ほどは GetID だけで済んだが、当然の流れとして GetDescription も Projects のメンバにすべきという話になるはずだ。
</p>

<pre><code>
<span class="synType">class</span> Projects {
<span class="synStatement">public</span>:
  <span class="synType">int</span> GetID(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → ID</span>
  <span class="synType">const</span> std::string&amp; GetDescription(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → プロジェクトの説明</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
つまり、デメテルの法則に従って Projects クラスを定義していくと、Project にメンバが追加される度に Projects メンバの追加を検討することになる。
</p>

<p>
実際に Project に「メンバ」を足してみることにしよう。
</p>

<pre><code>
<span class="synType">class</span> Member {
<span class="synStatement">public</span>:
  <span class="synType">const</span> string&amp; GetName() <span class="synType">const</span>;

  <span class="synComment">//...</span>
};

<span class="synType">class</span> Project {
<span class="synStatement">public</span>:
  <span class="synType">const</span> std::string&amp; GetName() <span class="synType">const</span>; <span class="synComment">// プロジェクト名</span>
  <span class="synType">int</span> GetID() <span class="synType">const</span>; <span class="synComment">// ID</span>
  <span class="synType">const</span> std::string&amp; GetDescription() <span class="synType">const</span>; <span class="synComment">// プロジェクトの説明</span>
  <span class="synType">const</span> Member&amp; GetLeader() <span class="synType">const</span>; <span class="synComment">// リーダは一人だけ</span>
  <span class="synType">const</span> std::vector&lt;Member&gt;&amp; GetMembers() <span class="synType">const</span>; <span class="synComment">// 全メンバ（リーダも含む）</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
メンバ違いなのはさておき、Projects からプロジェクトリーダやメンバの名前を取得するようなコードは、デメテルの法則に従えば次のようなものになるはずだ。
</p>

<pre><code>
string leaderName = projects.GetLeaderName(projectName);
vector&lt;string&gt; membersName = projects.GetMembersName(projectName);
<span class="synComment">// or</span>
string memberName = projects.GetMemberName(projectName, index); <span class="synComment">// 一人ずつ取得しても良い</span>

</code></pre>

<p>
これを実現するためには、Projects クラスに GetLeaderName, GetMembersName あるいは GetMemberName といった関数を追加しなければならない。
</p>

<pre><code>
<span class="synType">class</span> Projects {
<span class="synStatement">public</span>:
  <span class="synType">int</span> GetID(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → ID</span>
  <span class="synType">const</span> std::string&amp; GetDescription(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → プロジェクトの説明</span>

  <span class="synComment">// プロジェクト名 → プロジェクトリーダ名</span>
  <span class="synType">const</span> std::string&amp; GetLeaderName(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>;

  <span class="synComment">// 全メンバ（リーダも含む）の名前を一括で取得する</span>
  <span class="synComment">// （他にも色々な実装が考えられるが、今回の話題ではこれで充分）</span>
  <span class="synType">const</span> std::vector&lt;std::string&gt;&amp; GetMembersName(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>;

  <span class="synComment">// こちらの方が「戻り値のメンバを使わない」という観点から、より LoD 的な実装</span>
  std::<span class="synType">size_t</span> GetMemberCount(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// メンバの数</span>
  <span class="synType">const</span> std::string&amp; GetMemberName(<span class="synType">const</span> std::string&amp; name, <span class="synType">int</span> index) <span class="synType">const</span>; <span class="synComment">// メンバ名</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
以降、同様に Projects のメンバは肥大化の一途をたどることになる。私が Projects クラスのユーザなら「もう、いっそのこと Project に依存させてくれ！」と叫んでいるところだ。（そして多分 Member クラスも同じ理由で依存したくなるはず。）
</p>

<p>
さらに、Project や Member のインタフェースだけが肥大化の要因ではない。
</p>

<p>
プロジェクト名から何らかの情報を得るというインタフェースの他に、プロジェクト ID からも情報を得たいという要求が挙がった時のことを考えてみよう。デメテルの法則に従えば、プロジェクト ID をキーにした一連のメソッド群を用意すべし、となる。
</p>

<pre><code>
<span class="synType">class</span> Projects {
<span class="synStatement">public</span>:
  <span class="synType">int</span> GetID(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → ID</span>
  <span class="synType">const</span> std::string&amp; GetDescription(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → プロジェクトの説明</span>
  <span class="synType">const</span> std::string&amp; GetLeaderName(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → プロジェクトリーダ名</span>
  <span class="synType">const</span> std::vector&lt;std::string&gt;&amp; GetMembersName(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → 全メンバ名</span>
  std::<span class="synType">size_t</span> GetMemberCount(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → メンバの数</span>
  <span class="synType">const</span> std::string&amp; GetMemberName(<span class="synType">const</span> std::string&amp; name, <span class="synType">int</span> index) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → メンバ名</span>

<span class="synStatement">public</span>:
  <span class="synType">int</span> GetName(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → プロジェクト名</span>
  <span class="synType">const</span> std::string&amp; GetDescription(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → プロジェクトの説明</span>
  <span class="synType">const</span> std::string&amp; GetLeaderName(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → プロジェクトリーダ名</span>
  <span class="synType">const</span> std::vector&lt;std::string&gt;&amp; GetMembersName(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → 全メンバ名</span>
  std::<span class="synType">size_t</span> GetMemberCount(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → メンバの数</span>
  <span class="synType">const</span> std::string&amp; GetMemberName(<span class="synType">int</span> id, <span class="synType">int</span> index) <span class="synType">const</span>; <span class="synComment">// ID → メンバ名</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
以降、検索のキーが増える度に、同様のインタフェースが追加されることになる。
</p>

<p>
もし、デメテルの法則に従わなければ、先ほどのコードは次のようになっていたはずだ。
</p>

<pre><code>
<span class="synType">class</span> Projects {
<span class="synStatement">public</span>:
  <span class="synType">const</span> Project&amp; Find(<span class="synType">const</span> std::string&amp; name) <span class="synType">const</span>; <span class="synComment">// プロジェクト名 → Project クラス</span>
  <span class="synType">const</span> Project&amp; Find(<span class="synType">int</span> id) <span class="synType">const</span>; <span class="synComment">// ID → Project クラス</span>

  <span class="synComment">//...</span>
};

</code></pre>

<p>
これなら Find の種類が増えても Projects のメンバ関数はそれに応じて増えるだけだし、Project のメンバが増えても Projects に影響はない。先ほどよりも遥かに直交性の高いプログラムになっている。
</p>

<p>
そもそも Projects というクラスは Project を一括して管理するという役割を担っていたはずだ。リーダ名を取得するメソッドが「Project を一括して管理する」という役割に沿ったものだろうか。いや、とてもそうは思えない。こういった、クラスの役割とは異なるメンバ関数が多く含まれるクラスのことを凝集度が低いクラスと呼び、デメテルの法則に従って改変した Projects クラスは凝集度が低いクラスに変化したことになる。
</p>

<p>
ちなみに、Projects が Find によって Project を直接返すなら、プロジェクトリーダの名前を取得するコードは次のようになるだろう。
</p>

<pre><code>
string leaderName = projects.Find(projectName).GetLeader().GetName();
<span class="synComment">// あるいは</span>
string leaderName = projects.Find(projectID).GetLeader().GetName();

</code></pre>

<p>
まさに「デメテルの法則違反」なコードだ。でも、私は Projects が肥大化するよりはこの方がマシだと思えるのだが、そういった感覚はおかしいのだろうか？ 直交性を犠牲にしてまで従うべき法則なのだろうか？
</p>

<p>
デメテルの法則に従うと得られるメリットは以下の通り。
</p>

<ul>
<li>依存するクラスの数を減らすことができる（結合度の低下）</li>
<li>中間部分のインタフェースが変更されても、呼び出し側のコードを変更する必要がなくなる</li>
<li>中間クラスが持つ不要なインタフェースを隠蔽できる（むしろ隠蔽すべき）</li>
</ul>

<p>
これに対するデメリットは以下の通り。
</p>

<ul>
<li>クラスの役割があいまいになる（凝集度の低下）</li>
<li>場合によってはラッパーメソッド（委譲に必要なメンバ関数）が大量に必要となる</li>
</ul>

<p>
結局のところ、メリットとデメリットのトレードオフなだけであって、闇雲にデメテルの法則に従う必要はないはずだ。「それ、デメテルの法則に違反してるよ」と言われた時に、「それでは、直交性や凝集度を考慮した上でクラスのインタフェースを再検討してみましょう」と言ってみるのも面白いだろう。
</p>

<p>
極端な話、以下のコードだってデメテルの法則に違反している。
</p>

<pre><code>
vector&lt;Member&gt; members;
<span class="synComment">//...</span>
<span class="synStatement">for</span> (<span class="synType">size_t</span> i = <span class="synConstant">0</span>; i &lt; members.size(); ++i)
  cout &lt;&lt; members[i].GetName() &lt;&lt; endl;

</code></pre>

<p>
そう見えなければ、こう書き換えてもいい。
</p>

<pre><code>
vector&lt;Member&gt; members;
<span class="synComment">//...</span>
<span class="synStatement">for</span> (<span class="synType">size_t</span> i = <span class="synConstant">0</span>; i &lt; members.size(); ++i)
  cout &lt;&lt; members.<span class="synStatement">operator</span>[](i).GetName() &lt;&lt; endl; <span class="synComment">// ドットが2つ！ LoD 違反！</span>

</code></pre>

<p>
これをこう書き換えればデメテルの法則を違反せずに済むが......
</p>

<pre><code>
<span class="synStatement">for</span> (<span class="synType">size_t</span> i = <span class="synConstant">0</span>; i &lt; members.size(); ++i) {
  <span class="synType">const</span> Member&amp; member = members[i];
  cout &lt;&lt; member.GetName() &lt;&lt; endl; <span class="synComment">// OK. ドットは一つだけだ</span>
}

</code></pre>

<p>
それを強制させられるような職場なら、本気で転職を考えたほうが良いだろう。
</p>

<h3>参考文献</h3>

<p>
<a href="http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf">The Paperboy, The Wallet, and The Law of Demeter (PDF)</a>
</p>

<p>
このエントリが LoD に批判的なものになってしまったので、肯定的な文献を参考に挙げておく。英文だが、現実の世界をモチーフにしたサンプルコードが分かりやすく、英語そのものも読みやすいのでお奨め。
</p>

<p>
今回は意図的に LoD に不利な条件を作り出したが、隠蔽すべきものは隠蔽するというカプセル化の大原則を忘れてはならない。トレードオフを考えつつ、LoD に従うべきときは素直に従うべし。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/07/22-111055.html</link>
            <guid>http://zakio.net/blog/2009/07/22-111055.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">OOP</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">オブジェクト指向</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">プログラミング</category>
            
            <pubDate>Wed, 22 Jul 2009 11:10:55 +0900</pubDate>
        </item>
        
        <item>
            <title>仮想関数を generic にする</title>
            <description>
                <![CDATA[<p>
<a href="http://zakio.net/blog/2009/03/19-214446.html">C++では、メンバ関数テンプレートを仮想関数にできない</a>。ところが、C++/CLI ではテンプレートに良く似た機能である generic を仮想関数につけることができる。これにはどんなトリックが隠されているのだろう？
</p>

<p>
まずは、次のようなコードから。
</p>

<pre><code>
<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Base <span class="synComment">// ref class なので参照型</span>
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt; <span class="synComment">// generic を仮想関数につける</span>
  <span class="synType">virtual</span> <span class="synType">int</span> Func(T <span class="synStatement">in</span>) { <span class="synComment">// T は任意の型</span>
      <span class="synStatement">return</span> <span class="synStatement">sizeof</span>(<span class="synStatement">in</span>); <span class="synComment">// T 型のサイズを返す（本当は size_t だけど）</span>
  }
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Derived: <span class="synStatement">public</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> <span class="synType">int</span> Func(T <span class="synStatement">in</span>) <span class="synType">override</span> { <span class="synComment">// Base::Func を override</span>
      <span class="synStatement">return</span> <span class="synStatement">sizeof</span>(<span class="synStatement">in</span>) * <span class="synConstant">2</span>; <span class="synComment">// T 型のサイズを倍にして返す</span>
  }
};

</code></pre>

<p>
これはTがどんな型であっても正しく動作する。Derived のインスタンスを Base のハンドルで参照しても、Derived 側の Func が呼ばれる。完璧だ。
</p>

<p>
C++ では、Tの型が決まらないと仮想関数テーブルを構築できず、Tの型を知るためには全ての翻訳単位を調べなければならない。よって、このようなメンバ関数は禁止されている。そして、<a href="http://zakio.net/blog/2009/03/19-214446.html">以前のエントリ</a>では「なんだ、その都度 JIT コンパイルすればいいじゃん」という結論で終わっていた。今回は、これをもう少し調べてみようと思う。
</p>]]>
                <![CDATA[<p>
「JIT コンパイルすればいいじゃん」と言ってはみたものの、JIT コンパイラはソースコードを直接ネイティブコードにコンパイルするわけではない。ソースコードは MSIL という中間言語にコンパイルされており、JIT コンパイラは、この MSIL をネイティブコードにコンパイルするだけだ。
</p>

<p>
ということは、C++ の「仮想関数テーブル作成問題」は、この MSIL を作成する段階で問題にならないだろうか。先ほどのコードを ILDasm で見てみると、このようなコードになっていた。
</p>

<pre><code>
.method <span class="synStatement">public</span> hidebysig newslot <span class="synType">virtual</span> 
        instance int32  Func&lt;T&gt;(!!T '<span class="synStatement">in</span>') cil managed
{
  <span class="synComment">// Code size       9 (0x9)</span>
  .maxstack  <span class="synConstant">1</span>
  .locals ([<span class="synConstant">0</span>] int32 V_0)
  <span class="synStatement">IL_0000</span>:  <span class="synStatement">sizeof</span>     !!T
  <span class="synStatement">IL_0006</span>:  stloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_0007</span>:  ldloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_0008</span>:  ret
} <span class="synComment">// end of method Base::Func</span>

.method <span class="synStatement">public</span> hidebysig <span class="synType">virtual</span> instance int32 
        Func&lt;T&gt;(!!T '<span class="synStatement">in</span>') cil managed
{
  <span class="synComment">// Code size       11 (0xb)</span>
  .maxstack  <span class="synConstant">2</span>
  .locals ([<span class="synConstant">0</span>] int32 V_0)
  <span class="synStatement">IL_0000</span>:  <span class="synStatement">sizeof</span>     !!T
  <span class="synStatement">IL_0006</span>:  ldc.i4<span class="synConstant">.2</span>
  <span class="synStatement">IL_0007</span>:  mul
  <span class="synStatement">IL_0008</span>:  stloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_0009</span>:  ldloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_000a</span>:  ret
} <span class="synComment">// end of method Derived::Func</span>

</code></pre>

<p>
よく見ると、なんと T が T のままコンパイルされている。そして、sizeof が T をそのまま処理している。MSIL のレベルで T を T として扱っているということは、JIT コンパイルの段階で T の型に応じたネイティブコードを生成可能ということ。なるほど、ここまでは予想通り。
</p>

<p>
でも、これは MSIL の sizeof が T を T として扱えることに頼っている。sizeof じゃなかったらどうなるのだろう。
</p>

<pre><code>
<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;ToString(); <span class="synComment">// 今度は T に対して ToString メソッドを呼び出してみた</span>
  }
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Derived: <span class="synStatement">public</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) <span class="synType">override</span> {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;ToString() + <span class="synConstant">&quot; (Derived)&quot;</span>; <span class="synComment">// Derived 側の処理も上書き</span>
  }
};

</code></pre>

<p>
今度は T 型の変数 in に対して ToString メソッドを呼び出してみた。ILDasm の出力は次の通り。
</p>

<pre><code>
.method <span class="synStatement">public</span> hidebysig newslot <span class="synType">virtual</span> 
        instance string  Func&lt;T&gt;(!!T '<span class="synStatement">in</span>') cil managed
{
  <span class="synComment">// Code size       16 (0x10)</span>
  .maxstack  <span class="synConstant">1</span>
  .locals ([<span class="synConstant">0</span>] string V_0)
  <span class="synStatement">IL_0000</span>:  ldarga.s   '<span class="synStatement">in</span>'
  <span class="synStatement">IL_0002</span>:  constrained. !!T
  <span class="synStatement">IL_0008</span>:  callvirt   instance string [mscorlib]System.Object::ToString()
  <span class="synStatement">IL_000d</span>:  stloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_000e</span>:  ldloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_000f</span>:  ret
} <span class="synComment">// end of method Base::Func</span>

.method <span class="synStatement">public</span> hidebysig <span class="synType">virtual</span> instance string 
        Func&lt;T&gt;(!!T '<span class="synStatement">in</span>') cil managed
{
  <span class="synComment">// Code size       26 (0x1a)</span>
  .maxstack  <span class="synConstant">2</span>
  .locals ([<span class="synConstant">0</span>] string V_0)
  <span class="synStatement">IL_0000</span>:  ldarga.s   '<span class="synStatement">in</span>'
  <span class="synStatement">IL_0002</span>:  constrained. !!T
  <span class="synStatement">IL_0008</span>:  callvirt   instance string [mscorlib]System.Object::ToString()
  <span class="synStatement">IL_000d</span>:  ldstr      <span class="synConstant">&quot; (Derived)&quot;</span>
  <span class="synStatement">IL_0012</span>:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  <span class="synStatement">IL_0017</span>:  stloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_0018</span>:  ldloc<span class="synConstant">.0</span>
  <span class="synStatement">IL_0019</span>:  ret
} <span class="synComment">// end of method Derived::Func</span>

</code></pre>

<p>
IL_0008 の部分で、<a href="http://msdn.microsoft.com/ja-jp/library/system.reflection.emit.opcodes.callvirt.aspx">callvirt</a> という命令を使って Object::ToString() を呼び出している。この部分に T はなく、T は1つ前の <a href="http://msdn.microsoft.com/ja-jp/library/system.reflection.emit.opcodes.constrained.aspx">constrained</a> で使われている。T がどんな型であっても constrained が良きに計らってくれて、実行時の型に応じた ToString() が呼ばれるというわけだ。すばらしい。
</p>

<p>
ToString は System::Object のメソッドなので、どんな型からも（場合によってはボックス化を伴って）呼び出すことができる。もう少しハードルを上げてみよう。T という型が持っている「かも知れない」メソッドを呼び出してみたらどうだろう。
</p>

<pre><code>
<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func1(); <span class="synComment">// エラー: T は System::Object と見なされるため、Func1 は呼べない</span>
  }
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Derived: <span class="synStatement">public</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) <span class="synType">override</span> {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func2(); <span class="synComment">// エラー: Func2 も System::Object のメンバではない</span>
  }
};

</code></pre>

<p>
エラーだ。コンパイルできない。どうやら System::Object のメンバではないメソッドを呼び出すことができないようだ。このエラーを取り除くためには、次のように T が何者なのかを教えてやる必要がある。
</p>

<pre><code>
<span class="synStatement">public</span> interface <span class="synType">class</span> HasFunc {
  System::String^ Func1();
  System::String^ Func2();
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt; <span class="synStatement">where</span> T: HasFunc <span class="synComment">// T が何者かを教える</span>
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func1(); <span class="synComment">// T は HasFunc なので、Func1 を呼べる</span>
  }
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Derived: <span class="synStatement">public</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">generic</span> &lt;<span class="synType">typename</span> T&gt; <span class="synComment">// override しているので、T が HasFunc であることは既知</span>
  <span class="synType">virtual</span> System::String^ Func(T <span class="synStatement">in</span>) <span class="synType">override</span> {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func2(); <span class="synComment">// T は HasFunc なので、Func2 を呼べる</span>
  }
};

</code></pre>

<p>
ふむふむ、なるほど。先ほどは T が何者なのか分からなかったので、どんな型からも呼び出すことができる System::Object のメソッドしか受け付けなかったというわけか。今回は、T が HasFunc というインタフェースを持っていることが分かっているので、Func1 も Func2 を呼び出せる......って、当たり前じゃないか。
</p>

<p>
それなら、こんな風にしても同じ事。インタフェースを知る必要があるなら、あえて generic にしなくても書ける。
</p>

<pre><code>
<span class="synStatement">public</span> interface <span class="synType">class</span> HasFunc {
  System::String^ Func1();
  System::String^ Func2();
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">virtual</span> System::String^ Func(HasFunc^ <span class="synStatement">in</span>) { <span class="synComment">// 無理に generic にしなくても、こうすればよいだけ</span>
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func1(); <span class="synComment">// in は HasFunc なので、Func1 を呼び出せる</span>
  }
};

<span class="synStatement">public</span> <span class="synType">ref</span> <span class="synType">class</span> Derived: <span class="synStatement">public</span> Base
{
<span class="synStatement">public</span>:
  <span class="synType">virtual</span> System::String^ Func(HasFunc^ <span class="synStatement">in</span>) <span class="synType">override</span> {
      <span class="synStatement">return</span> <span class="synStatement">in</span>-&gt;Func2(); <span class="synComment">// Func2 も呼び出せる</span>
  }
};

</code></pre>

<p>
.NET の generics は、コンパイル時にソースコードを要求しないという利点を求めた結果、多分、C++ ユーザにとって template を使う大きな理由の一つである「静的なダックタイピング」を切り捨てざるを得なかったのだろう。
</p>

<p>
これまで generic を template のようなものだと思っていたが、これではまるで別物だ。考えを改めなければならない。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/06/01-133549.html</link>
            <guid>http://zakio.net/blog/2009/06/01-133549.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET Framework</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++/CLI</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++/CLI</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">generics</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">template</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">virtual</category>
            
            <pubDate>Mon, 01 Jun 2009 13:35:49 +0900</pubDate>
        </item>
        
        <item>
            <title>Pimpl イディオムのお手軽な実装</title>
            <description>
                <![CDATA[<p>
Pimpl イディオム（Handle-Body, Compilation or Compiler Firewall, Cheshire Cat とも呼ばれたりする）は実装の詳細を隠蔽したい時に用いられる手法だが、内部が委譲の嵐になったり、ポインタの扱いに注意を払う必要があったりと、気軽には使い難いパターンの一つではある。内部の委譲に関しては Pimpl の性質上仕方がないものとして諦められるが、せめてポインタ周りだけでもお手軽に扱えるようにならないだろうか、というのが今回のお題だ。
</p>

<p>
教科書に載っているような Pimpl の実装は、大抵の場合、次の例の前半部分まで。こうやって隠蔽した Impl のポインタ pImpl_ を正しく扱うためには、コンストラクタ、デストラクタ、コピーコンストラクタ、代入演算子を「正しく」実装しなければならない。
</p>

<pre><code>
<span class="synType">class</span> PimplTest {
<span class="synStatement">public</span>:
  <span class="synComment">// ... 外部に公開するインタフェース</span>

<span class="synStatement">private</span>:
  <span class="synType">class</span> Impl; <span class="synComment">// 実装の詳細は Impl に隠蔽し、</span>
  Impl* pImpl_; <span class="synComment">// そのポインタを保持する</span>

<span class="synComment">// Impl を正しく扱うためには、以下のコードを「正しく」書かなければならない</span>
<span class="synStatement">public</span>:
  PimplTest(); <span class="synComment">// ここで new</span>
  ~PimplTest(); <span class="synComment">// ここで delete</span>
  PimplTest(<span class="synType">const</span> PimplTest&amp; obj); <span class="synComment">// Impl に対する深いコピーが必要</span>
  PimplTest&amp; <span class="synStatement">operator</span> = (<span class="synType">const</span> PimplTest&amp; rhs); <span class="synComment">// こちらも同様に深いコピー</span>
};

</code></pre>

<p>
時々、ポインタ周りを楽にするために shared_ptr を使って Pimpl イディオムを実装している例を見かけるが、これではコピーや代入時に実装の詳細が共有されてしまう。コピーや代入を禁止しても構わない場合ならこれで充分かも知れないが、そうでない場合は自前のコピーコンストラクタや代入演算子を用意する必要があるため、やはり、お手軽とは言い難いだろう。
</p>]]>
                <![CDATA[<p>
例えば、先ほどの例を少しだけ肉付けして、shared_ptr を使った例に書き換えると次のようになる。
</p>

<pre><code>
<span class="synType">class</span> PimplTest {
<span class="synStatement">public</span>:
  PimplTest();

<span class="synComment">// 値の読み書きを表現</span>
<span class="synStatement">public</span>:
  <span class="synType">void</span> SetVal(<span class="synType">int</span> val);
  <span class="synType">int</span> GetVal() <span class="synType">const</span>;

<span class="synComment">// 実装の詳細</span>
<span class="synStatement">private</span>:
  <span class="synType">class</span> Impl;
  std::tr1::shared_ptr&lt;Impl&gt; pImpl_; <span class="synComment">// コピーさえしなければ、これで間に合うが......</span>
};

</code></pre>

<p>
cpp 側はこんな感じ。
</p>

<pre><code>
<span class="synComment">// 実装の詳細</span>
<span class="synType">class</span> PimplTest::Impl {
  <span class="synType">int</span> val_;
<span class="synStatement">public</span>:
  Impl(): val_(<span class="synType">int</span>()) {}
  <span class="synType">void</span> SetVal(<span class="synType">int</span> val) { val_ = val; }
  <span class="synType">int</span> GetVal() <span class="synType">const</span> { <span class="synStatement">return</span> val_; }
};

<span class="synComment">// コンストラクタで new するだけなので楽チン</span>
PimplTest::PimplTest(): pImpl_(<span class="synStatement">new</span> Impl) {}

<span class="synComment">// 委譲の嵐</span>
<span class="synType">void</span> PimplTest::SetVal(<span class="synType">int</span> val) { pImpl_-&gt;SetVal(val); }
<span class="synType">int</span> PimplTest::GetVal() <span class="synType">const</span> { <span class="synStatement">return</span> pImpl_-&gt;GetVal(); }

</code></pre>

<p>
このように実装してしまうと、shared_ptr が持つ「コピー時に参照先（この場合は Impl のインスタンス）を共有する」という性質から、次のような問題が生じてしまう。
</p>

<pre><code>
<span class="synComment">// PimplTest のインスタンスに 1 と 2 をセットする</span>
PimplTest test1, test2;
test1.SetVal(<span class="synConstant">1</span>);
test2.SetVal(<span class="synConstant">2</span>);

<span class="synComment">// 当然、1, 2 と表示される</span>
cout &lt;&lt; test1.GetVal() &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; test2.GetVal() &lt;&lt; endl;

test1 = test2; <span class="synComment">// test2 の内容を test1 に代入（これで test1 が 2 になるはず）</span>
test2.SetVal(<span class="synConstant">20</span>); <span class="synComment">// test2 は 20 に変更</span>

<span class="synComment">// 2, 20 と表示されることを期待するが、</span>
<span class="synComment">// 実際には test1 と test2 は同じ Impl を参照しているため、20, 20 と表示される</span>
cout &lt;&lt; test1.GetVal() &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; test2.GetVal() &lt;&lt; endl;

</code></pre>

<p>
つまり、Pimpl に適したスマートポインタは、次の2つの機能を兼ね備えていなければならないということだ。
</p>

<ol>
<li>不完全型を受け付ける（クラスの先行宣言だけでコンパイル可能）</li>
<li>値のセマンティクスを持つ（勝手に深いコピーをしてくれる）</li>
</ol>

<p>
shared_ptr は1つ目の機能を deleter によって実現しているが、残念ながら2番目の機能が期待通りではない。どこかに上記の機能を兼ね備えた Pimpl に最適なスマートポインタはないかと探し回ったが、探し方が悪いのだろう。満足のいくものを見つけることは出来なかった。そこで、勉強も兼ねて自作に踏み切ってみることにした。車輪の再発明かも知れないが、結構勉強になったので私的には大満足だ。
</p>

<p>
気に入った方は好きに使っていただいて構わないし、改変や商用利用、その他諸々何でもアリ。ただし、当然ながら無保証なのでご注意を。
</p>

<p>
この特別な Pimpl イディオム用のスマートポインタ Pimpl を使えば、先ほどのコードが次のように変化し、
</p>

<pre><code>
<span class="synType">class</span> PimplTest {
<span class="synStatement">public</span>:
  PimplTest();

<span class="synStatement">public</span>:
  <span class="synType">void</span> SetVal(<span class="synType">int</span> val);
  <span class="synType">int</span> GetVal() <span class="synType">const</span>;

<span class="synStatement">private</span>:
  <span class="synType">class</span> Impl;
  Pimpl&lt;Impl&gt; pImpl_; <span class="synComment">// この部分を Pimpl に変更</span>
};

</code></pre>

<p>
実行結果も期待通りになる。
</p>

<pre><code>
<span class="synComment">// PimplTest のインスタンスに 1 と 2 をセットする</span>
PimplTest test1, test2;
test1.SetVal(<span class="synConstant">1</span>);
test2.SetVal(<span class="synConstant">2</span>);

<span class="synComment">// 当然、1, 2 と表示される</span>
cout &lt;&lt; test1.GetVal() &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; test2.GetVal() &lt;&lt; endl;

test1 = test2; <span class="synComment">// test2 の内容を test1 に代入して、</span>
test2.SetVal(<span class="synConstant">20</span>); <span class="synComment">// test2 は 20 に変更</span>

<span class="synComment">// 今度は期待通り 2, 20 と表示される</span>
cout &lt;&lt; test1.GetVal() &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; test2.GetVal() &lt;&lt; endl;

</code></pre>

<p>
Pimpl の実装は以下の通り。これを適当な namespace に入れてインクルードガードを付ければ Pimpl.h の完成だ。結構便利に使えると思うのだが如何だろう。
</p>

<pre><code>
<span class="synComment">// 不完全型を受け付けるためのインタフェース</span>
<span class="synComment">// ポインタを void* で扱っている部分がミソ</span>
<span class="synType">class</span> ImplHolderBase {
<span class="synStatement">public</span>:
  <span class="synType">virtual</span> ~ImplHolderBase() {}
  <span class="synType">virtual</span> ImplHolderBase* Clone() <span class="synType">const</span> = <span class="synConstant">0</span>;
  <span class="synType">virtual</span> <span class="synType">void</span> CopyTo(ImplHolderBase* pHolder) <span class="synType">const</span> = <span class="synConstant">0</span>;
  <span class="synType">virtual</span> <span class="synType">void</span>* GetPtr() = <span class="synConstant">0</span>;
  <span class="synType">virtual</span> <span class="synType">const</span> <span class="synType">void</span>* GetPtr() <span class="synType">const</span> = <span class="synConstant">0</span>;
};

<span class="synComment">// ポインタを保持するクラス</span>
<span class="synType">template</span> &lt;<span class="synType">class</span> T&gt;
<span class="synType">class</span> ImplHolder: <span class="synStatement">public</span> ImplHolderBase {
  T* ptr_; <span class="synComment">// これが Impl の実体</span>
<span class="synStatement">public</span>:
  <span class="synType">explicit</span> ImplHolder(T* ptr): ptr_(ptr) {}
  <span class="synType">virtual</span> ~ImplHolder() {
      <span class="synStatement">delete</span> ptr_;
  }
  <span class="synType">virtual</span> ImplHolderBase* Clone() <span class="synType">const</span> {
      <span class="synStatement">return</span> <span class="synStatement">new</span> ImplHolder(<span class="synStatement">new</span> T(*ptr_)); <span class="synComment">// ここで T のコピーコンストラクタが呼ばれる</span>
  }
  <span class="synType">virtual</span> <span class="synType">void</span> CopyTo(ImplHolderBase* pHolder) <span class="synType">const</span> {
      <span class="synComment">// ImplHolder 以外は考えられないので、static_cast で変換可能</span>
      *(<span class="synStatement">static_cast</span>&lt;ImplHolder*&gt;(pHolder)-&gt;ptr_) = *ptr_; <span class="synComment">// ここで T の代入演算子が呼ばれる</span>
  }
  <span class="synType">virtual</span> <span class="synType">void</span>* GetPtr() { <span class="synStatement">return</span> ptr_; }
  <span class="synType">virtual</span> <span class="synType">const</span> <span class="synType">void</span>* GetPtr() <span class="synType">const</span> { <span class="synStatement">return</span> ptr_; }
<span class="synStatement">private</span>: <span class="synComment">// 念のためコピーと代入を禁止しておく</span>
  ImplHolder(<span class="synType">const</span> ImplHolder&amp;); <span class="synComment">// 未実装</span>
  ImplHolder&amp; <span class="synStatement">operator</span> = (<span class="synType">const</span> ImplHolder&amp;); <span class="synComment">// 未実装</span>
};

<span class="synComment">// Pimpl クラスの実体</span>
<span class="synType">template</span> &lt;<span class="synType">class</span> T&gt;
<span class="synType">class</span> Pimpl {
  ImplHolderBase* pHolder_; <span class="synComment">// T に依存しない</span>
<span class="synStatement">public</span>:
  <span class="synType">explicit</span> Pimpl(T* ptr): pHolder_(<span class="synStatement">new</span> ImplHolder&lt;T&gt;(ptr)) {} <span class="synComment">// この時点で T の型が決まる</span>
  ~Pimpl() {
      <span class="synStatement">delete</span> pHolder_; <span class="synComment">// T が不完全型でも問題ない</span>
  }
  Pimpl(<span class="synType">const</span> Pimpl&amp; init): pHolder_(init.pHolder_-&gt;Clone()) {} <span class="synComment">// コピーコンストラクタは Clone で対応</span>
  Pimpl&amp; <span class="synStatement">operator</span> = (<span class="synType">const</span> Pimpl&amp; rhs) {
      rhs.pHolder_-&gt;CopyTo(pHolder_); <span class="synComment">// 代入は CopyTo で対応</span>
      <span class="synStatement">return</span> *<span class="synStatement">this</span>;
  }
  T&amp; <span class="synStatement">operator</span> * () { <span class="synStatement">return</span> *(<span class="synStatement">static_cast</span>&lt;T*&gt;(pHolder_-&gt;GetPtr())); }
  <span class="synType">const</span> T&amp; <span class="synStatement">operator</span> * () <span class="synType">const</span> { <span class="synStatement">return</span> *(<span class="synStatement">static_cast</span>&lt;<span class="synType">const</span> T*&gt;(pHolder_-&gt;GetPtr())); }
  T* <span class="synStatement">operator</span> -&gt; () { <span class="synStatement">return</span> &amp;(**<span class="synStatement">this</span>); }
  <span class="synType">const</span> T* <span class="synStatement">operator</span> -&gt; () <span class="synType">const</span> { <span class="synStatement">return</span> &amp;(**<span class="synStatement">this</span>); }
};

</code></pre>

<p>
ぜひ、お試しあれ！
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/04/15-222117.html</link>
            <guid>http://zakio.net/blog/2009/04/15-222117.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">Pimpl</category>
            
            <pubDate>Wed, 15 Apr 2009 22:21:17 +0900</pubDate>
        </item>
        
        <item>
            <title>コレクションの永続化</title>
            <description>
                <![CDATA[<p>
.NET Framework で独自のコントロールを作りたい場合は、UserControl から派生させたクラスを用意すればよい。一般的に、自作コントロールには独自のプロパティも含まれており、そのプロパティが自作クラスになっていることも多いはず。今回は、自作クラスの配列をプロパティとして持たせたところ大ハマリしたという話。
</p>

<p>
ある自作コントロールに自作クラス MyItem の配列をプロパティとして持たせたいと思い、System::Collections::Generic::List&lt;MyItem^&gt;^ 型のプロパティ MyItemList を追加することにした。cli::array ではなく List を使っているのは vector っぽく使いたいためだが、この違いは本質ではない（と思う）。悲劇の始まりは次のようなコードからだ。
</p>

<pre><code>
<span class="synType">ref</span> <span class="synType">class</span> MyItem;
<span class="synType">ref</span> <span class="synType">class</span> MyCtrl : <span class="synStatement">public</span> System::Windows::Forms::UserControl
{
<span class="synComment">// ... 色々あって、</span>

<span class="synStatement">private</span>:
  System::Collections::Generic::List&lt;MyItem^&gt;^ m_itemList; <span class="synComment">// リストの実体</span>

<span class="synStatement">public</span>:
  MyCtrl(<span class="synType">void</span>) {
      InitializeComponent();

      <span class="synComment">// コンストラクタで m_itemList を確保する</span>
      m_itemList = <span class="synStatement">gcnew</span> System::Collections::Generic::List&lt;MyItem^&gt;;
  }

<span class="synStatement">public</span>:
  <span class="synType">property</span> System::Collections::Generic::List&lt;MyItem^&gt;^ MyItemList { <span class="synComment">// このプロパティは</span>
      System::Collections::Generic::List&lt;MyItem^&gt;^ get() { <span class="synComment">// get だけしか持っていない（set は許可しない）</span>
          <span class="synStatement">return</span> m_itemList; <span class="synComment">// 中身は自由にしても構わないが、リストそのものはコチラで管理させてくれ</span>
      }
  }

<span class="synComment">// ... 色々あるよね</span>
};

</code></pre>]]>
                <![CDATA[<p>
C++/CLI は const まわりが貧弱なので不安でたまらなくなるが、せめてもの反抗として MyItemList プロパティからは set を取り除いてみた。ちなみに MyItem 自体はラベルやら色やらの情報が格納された単純なもの。このコントロールは MyItemList 内の MyItem 群を描画するのが目的だ。
</p>

<pre><code>
<span class="synComment">// リストに格納されるモノ</span>
<span class="synType">ref</span> <span class="synType">class</span> MyItem {
<span class="synStatement">public</span>:
  <span class="synType">property</span> System::String^ Label; <span class="synComment">// ラベルやら</span>
  <span class="synType">property</span> System::Drawing::Color ForeColor; <span class="synComment">// 色やら</span>
  <span class="synComment">// ... その他諸々（今回は省略）</span>
};

</code></pre>

<p>
コンパイルは成功するし、このコントロールをフォームに貼り付けることもできる。しかも、コントロールのプロパティには「その他」の項目として MyItemList が入っているというオマケ付き。コレクションの右にあるボタンをクリックすると MyItem のコレクションエディタが起動し、MyItemList に MyItem を追加したり編集したりと、もう至れり尽くせり状態だ。
</p>

<p>
コレクションエディタ上で MyItem を追加、編集して、いざコンパイル。
</p>

<p>
「あれ？ MyItem が消えたぞ」
</p>

<p>
何回やっても結果は同じ。コンパイルさえしなければ何も問題はないのだが、それでは意味がない。
</p>

<p>
色々調べた結果、MyItemList の <a href="http://msdn.microsoft.com/ja-jp/library/system.componentmodel.designerserializationvisibilityattribute(VS.80).aspx">DesignerSerializationVisibility 属性</a>を Content にしなければならないことが分かった（デフォルト値は Visible）。 こうすることで、MyItemList の Content、つまり「中身」を永続化可能にするというわけだ。
</p>

<pre><code>
[DesignerSerializationVisibility(DesignerSerializationVisibility::Content)] <span class="synComment">// これが必要</span>
<span class="synType">property</span> System::Collections::Generic::List&lt;MyItem^&gt;^ MyItemList {
  System::Collections::Generic::List&lt;MyItem^&gt;^ get() {
      <span class="synStatement">return</span> m_itemList;
  }
}

</code></pre>

<p>
これで MyItemList の中身が保存されるようになったのだが、今度はコレクションの中身が空でもデザイナ上ではボールド表示、つまり「初期値と違う」と主張し始めた。MyItemList 上の右クリックで初期化しようとしても、リセット自体がグレーアウトされている。
</p>

<p>
「あぁ、確かこれは <a href="http://msdn.microsoft.com/ja-jp/library/system.componentmodel.defaultvalueattribute(VS.80).aspx">DefaultValue 属性</a>だったな」と思ったが、今回は MyItemList を自前で管理しているため、リテラルとしての初期値が存在しない。初期値というよりは、初期化メソッドが必要なのだ。
</p>

<p>
さらに調査を進めると、こういう場合は <a href="http://msdn.microsoft.com/ja-jp/library/53b8022e(VS.80).aspx">ShouldSerialize, Reset メソッド</a>を使えばよいことが分かった。最初は何を言っているのか良く分からなかったのだが、どうやら .NET Framework では ShouldSerialize<em>プロパティ名</em> と Reset<em>プロパティ名</em>の2つのメソッド名を特別扱いするという仕様のようだ。
</p>

<p>
つまり、こういうこと。
</p>

<pre><code>
<span class="synComment">// MyItemList という名前のプロパティがあれば、</span>
<span class="synComment">// ShouldSerializeMyItemList と ResetMyItemList という2つのメソッドが特別扱いされる。</span>
[DesignerSerializationVisibility(DesignerSerializationVisibility::Content)]
<span class="synType">property</span> System::Collections::Generic::List&lt;MyItem^&gt;^ MyItemList {
  System::Collections::Generic::List&lt;MyItem^&gt;^ get() {
      <span class="synStatement">return</span> m_itemList;
  }
}
<span class="synComment">// このメソッドは「永続化すべきかどうか」つまり「初期値と違うかどうか」を返す</span>
<span class="synType">bool</span> ShouldSerializeMyItemList() {
  <span class="synStatement">return</span> m_itemList-&gt;Count &gt; <span class="synConstant">0</span>; <span class="synComment">// 空じゃなければ初期値でない</span>
}
<span class="synComment">// 「リセット」時に呼ばれるメソッド</span>
<span class="synType">void</span> ResetMyItemList() {
  m_itemList-&gt;Clear(); <span class="synComment">// 空にする</span>
}

</code></pre>

<p>
これで万事うまくいく...はずだった。しかし、肝心の「リセット」がグレーアウトされたままになっている。ここで悩むこと数時間。「ひょっとして、MyItemList に set がないからかも」と思い、次のように set を追加したら...動いてしまった。
</p>

<pre><code>
[DesignerSerializationVisibility(DesignerSerializationVisibility::Content)]
<span class="synType">property</span> System::Collections::Generic::List&lt;MyItem^&gt;^ MyItemList {
  System::Collections::Generic::List&lt;MyItem^&gt;^ get() {
      <span class="synStatement">return</span> m_itemList;
  }
  <span class="synComment">// これがないと「リセット」が有効にならない</span>
  <span class="synType">void</span> set(System::Collections::Generic::List&lt;MyItem^&gt;^ itemList) {
      <span class="synStatement">if</span> (!itemList) <span class="synComment">// 仕方がないので例外を投げることにした</span>
          <span class="synStatement">throw</span> <span class="synStatement">gcnew</span> System::Exception(<span class="synConstant">&quot;MyItemList must not be null.&quot;</span>);
      m_itemList = itemList;
  }
}
<span class="synType">bool</span> ShouldSerializeMyItemList() {
  <span class="synStatement">return</span> m_itemList-&gt;Count &gt; <span class="synConstant">0</span>;
}
<span class="synType">void</span> ResetMyItemList() {
  m_itemList-&gt;Clear();
}

</code></pre>

<p>
こういう仕様なのかどうかは分からないが、MyItemList に set が無いからという理由で ResetMyItemList が呼べないのは納得できない。ただでさえ const まわりが貧弱なのに、それに抵抗すると余計な労力を強いられるとは。ちなみに、現在の環境は Visual Studio 2008 SP1。次のバージョンでは何とかして欲しいところだが、今後 C++/CLI を使うかどうかは微妙なので、まぁどっちでもいいや。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/04/06-221625.html</link>
            <guid>http://zakio.net/blog/2009/04/06-221625.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">.NET Framework</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++/CLI</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">.NET Framework</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++/CLI</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">DesignerSerializationVisibility</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">UserControl</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">カスタムコントロール</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">永続化</category>
            
            <pubDate>Mon, 06 Apr 2009 22:16:25 +0900</pubDate>
        </item>
        
        <item>
            <title>C++でメンバ関数テンプレートを仮想関数にできないのは何故？</title>
            <description>
                <![CDATA[<p>
C++ でメンバ関数テンプレートを仮想関数にしようとして、コンパイラに怒られた経験がある人は多いと思う。
</p>

<pre><code>
<span class="synType">class</span> Hoge {
<span class="synStatement">public</span>:
  <span class="synType">template</span> &lt;<span class="synType">typename</span> T&gt;
  <span class="synType">virtual</span> <span class="synType">void</span> Func(<span class="synType">const</span> T&amp; in) {} <span class="synComment">// メンバ関数テンプレートは仮想関数にできない</span>
};

</code></pre>

<p>
こういう場合、クラスを丸ごとテンプレート化してしまえば何とかなる場合が多いので、どうしてもという時は設計を見直すことになるだろう。こうすれば仮想関数でテンプレート引数の型が使えるようになる。
</p>

<pre><code>
<span class="synType">template</span> &lt;<span class="synType">typename</span> T&gt; <span class="synComment">// テンプレートクラスにすれば、仮想関数で T が使える</span>
<span class="synType">class</span> Hoge {
<span class="synStatement">public</span>:
  <span class="synType">virtual</span> <span class="synType">void</span> Func(<span class="synType">const</span> T&amp; in) {}
};

</code></pre>]]>
                <![CDATA[<p>
仮想関数ではないメンバ関数テンプレートや、テンプレートではない仮想関数は可能なのに、この2つが合わさるとダメになってしまうのは何故なのだろう。短い答えは「そういう仕様だから」だ。C++ の標準規格書には、はっきり「ダメ」と書いてある。
</p>

<blockquote>
<p>A member function template shall not be virtual. [Example:<br />
&nbsp;&nbsp;&nbsp;&nbsp;template &lt;class T&gt; struct AA {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template &lt;class C&gt; virtual void g(C); // error<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual void f(); // OK<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
--end example]</p><br />
<p><cite>ISO/IEC 14882:2003, 14.5.2 Member templates - 3</cite></p>
</blockquote>

<p>
でも、これで終わってしまったら面白くないので、もう少し掘り下げてみよう。何故こういう仕様になったのだろうか。テンプレートクラスが仮想メンバ関数を持てるならば、仮想テンプレートメンバ関数を許してくれても良いではないか。
</p>

<p>
色々調べてみた結果、満足のいく答えは Stroustrup 氏の著書「プログラム言語 C++ 第3版」で見つけることができた。灯台下暗しとはこのことだ。
</p>

<blockquote>
<p>メンバテンプレートは、virtual 宣言できない。たとえば次の通り。</p><br />
<p>class Shape {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;template&lt;class T&gt; virtual bool intersect(const T&amp;) const = 0; // エラー: virtual テンプレート<br />
};</p><br />
<p>この例は、文法から逸脱しているものとして扱わなければならない。これを認めると、仮想関数を実装するために伝統的に使われてきた仮想関数テーブルテクニック（§2.5.5）が使えなくなる。誰かが新しい引数型を指定して intersect() を呼び出すたびに、リンカは Shape クラスの仮想テーブルに新しいエントリを追加しなければならなくなってしまう。</p><br />
<p><cite>プログラム言語 C++ 第3版, 13.6.2 メンバテンプレート</cite></p>
</blockquote>

<p>
なるほど、納得。全ての翻訳単位をコンパイルしてみないと、仮想関数テーブルが一意に定まらないというわけか。
</p>

<p>
ところで、何故「仕様だから」で済むような話にここまでこだわるのか。それは C# では仮想メンバ関数にジェネリクス（template のようなもの）が使えると聞いたからだ。C++ 以外の言語はサッパリなので、これを機に少し調べてみようと思ったのだが、その前に出来ない理由を明確にしておこうと思った次第。
</p>

<p>
C# はこの問題をどうやって解決しているのだろう......と、考えているうちに、なんとなく答えが分かったような気がする。C#（に限らず .NET 系全般）なら Just In Time でコンパイルしてしまえば良いではないか。無いものは作ればいい。リンカが困ったらコンパイル。たぶん、これだな。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/03/19-214446.html</link>
            <guid>http://zakio.net/blog/2009/03/19-214446.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">template</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ジェネリクス</category>
            
            <pubDate>Thu, 19 Mar 2009 21:44:46 +0900</pubDate>
        </item>
        
        <item>
            <title>Blender で favicon</title>
            <description>
                <![CDATA[<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="blender.png" src="http://zakio.net/blog/2009/03/blender.png" width="320" height="231" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></span><a href="http://www.blender.org/">Blender</a> で favicon を作ってみた。
</p>

<p>
Blender はフリーの 3DCG ソフト。操作方法にクセがありまくるため毎回イライラしながら作ることになるのだが、icon 系の画像を作る時にはナンダカンダ言いつつも結局  Blender を使っていることが多い。
</p>]]>
                <![CDATA[<p>
......と偉そうに書いているが、ちっとも使いこなせていないので質問は禁止。毎回、使うたびに初心者に逆戻りしているような状態だ。今回も、WBS+ というサイトにある<a href="http://wbs.nsf.tc/tutorial/tutorial_blender.html">「本当に初めての方のために作成したBlenderチュートリアル」</a>を参考にしながら、試行錯誤を繰り返すことになった。
</p>

<p>
favicon 程度の画像に Blender を使うのは大げさな感じがするかも知れないが、むしろ、基本的な機能だけで間に合ってしまう favicon だからこそ、全くの素人でもそれなりの画像が得られるとも言える。Blender を使えば絵の上手い下手は関係ない。物体を3次元で表現できれば、後は写真を撮る要領でイメージを切り取ってやるだけだ。
</p>

<p>
ところで、今回 favicon の画像に薬のカプセルを選んだのは、「zakio.net が悩めるエンジニアの処方箋になってくれれば」という強い思いがあった訳ではない。単にモデリングが簡単だったからだ。16 x 16 pixel では複雑なモデルを表現しきれないので、カプセル程度の単純なものの方が favicon には適していると思う。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="capsule.png" src="http://zakio.net/blog/2009/03/capsule.png" width="128" height="128" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></span>一応、カプセルの表面に zakio.net とプリントしてはみたが、16 x 16 の favicon では、そんな細部のこだわりは全くの無意味。本物のカプセルを参考にして微妙なくぼみを付けてみたりもしたが、その部分に至っては拡大してもこの有様だ。3DCG でリアリティを出すためには細部にこだわると良いらしいが、favicon でリアリティを追求する必要はこれっぽっちもない。ここまでくると単なる自己満足の世界である。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/03/11-025236.html</link>
            <guid>http://zakio.net/blog/2009/03/11-025236.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Blender</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">Blender</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">favicon</category>
            
            <pubDate>Wed, 11 Mar 2009 02:52:36 +0900</pubDate>
        </item>
        
        <item>
            <title>値型とボックス化</title>
            <description>
                <![CDATA[<p>
<a href="/blog/2009/02/25-215637.html">前回</a>の続き。
</p>

<p>
CLI は値型と参照型を区別する。一般に値型はスタック、参照型はヒープ上に配置されるが、C++/CLI では参照型であっても C++ と同じようにスタックに置くことができる。正確には「置いたように見せかける」だが、構文的にも意味的にもスタックに置いたオブジェクトと同じように扱える。
</p>

<pre><code>
List&lt;<span class="synType">int</span>&gt; list1; <span class="synComment">// 参照型なのにスタックに置ける（ように見える）</span>
List&lt;<span class="synType">int</span>&gt;* list2 = &amp;list1; <span class="synComment">// コンパイルエラー: CLI heap 上にあるオブジェクトはポインタで参照できない</span>
List&lt;<span class="synType">int</span>&gt;&amp; list3 = list1; <span class="synComment">// コンパイルエラー: CLI heap 上にあるオブジェクトはトラッキング参照を用いること</span>
List&lt;<span class="synType">int</span>&gt;^ list4 = %list1; <span class="synComment">// % でハンドルを取得</span>
List&lt;<span class="synType">int</span>&gt;% list5 = list1; <span class="synComment">// トラッキング参照は &amp; と同様の振る舞い</span>

</code></pre>

<p>
構文としてはスタックだが、参照型はあくまで参照型。実際のオブジェクトは CLI ヒープ上に存在するため、間接的に参照する場合はポインタではなくハンドルを使うことになる。つまり * → ^, &amp; → % のルールで自然に振舞うということ。ここまでは問題ない。混乱の元は値型だ。
</p>]]>
                <![CDATA[<p>
前回のエントリで、ハンドルは「CLI ヒープ用のポインタ」と述べた。CLI ヒープに確保したインスタンスをポインタで受けることはできないのだから、逆もまた然りと考えて当然である。スタックに置いた値型は CLI ヒープではなく本当にスタック上に置かれるから、ハンドルでは扱えないはずだ。
</p>

<pre><code>
<span class="synStatement">using</span> <span class="synType">namespace</span> System::Drawing;

Point pt1; <span class="synComment">// 値型をスタックに置く</span>
Point* pt2 = &amp;pt1; <span class="synComment">// 値型は CLI heap 上にないので、ポインタで参照できる</span>
Point&amp; pt3 = pt1; <span class="synComment">// &amp; も利用可</span>
Point^ pt4 = %pt1; <span class="synComment">// コンパイルエラーにならない！</span>
Point% pt5 = pt1; <span class="synComment">// コンパイルエラーにならない！</span>

</code></pre>

<p>
ハンドルでは扱えないはずだ......ったが、コンパイルエラーにはならない。どうやらこれがボックス化というもののようだ。ボックス化とは、値型のインスタンスをハンドルで扱うために、インスタンスを一旦 CLI ヒープに「暗黙に」コピーし、そのコピー先を指し示すというものだ。そんな無茶な。
</p>

<p>
それでは値を間接的に指し示すもの、ポインタとしての役割を果たしていないではないか。ボックス化によって得られたハンドルは、もはや、元のオブジェクトとは無縁の存在というわけだ。実験してみよう。
</p>

<pre><code>
Point pt(<span class="synConstant">0</span>, <span class="synConstant">0</span>); <span class="synComment">// 値型をスタック上に置く</span>
Point* pPt = &amp;pt; <span class="synComment">// ポインタで参照する</span>
Point^ hPt = %pt; <span class="synComment">// ハンドルで参照するとボックス化される</span>
pPt-&gt;X = <span class="synConstant">1</span>; <span class="synComment">// ポインタ経由で X を 1 にする</span>
hPt-&gt;Y = <span class="synConstant">2</span>; <span class="synComment">// ハンドル経由で Y を 2 にする</span>

cout &lt;&lt; <span class="synConstant">&quot;pPt = (&quot;</span> &lt;&lt; pPt-&gt;X &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; pPt-&gt;Y &lt;&lt; <span class="synConstant">&quot;)</span><span class="synSpecial">\n</span><span class="synConstant">&quot;</span>;
cout &lt;&lt; <span class="synConstant">&quot;hPt = (&quot;</span> &lt;&lt; hPt-&gt;X &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; hPt-&gt;Y &lt;&lt; <span class="synConstant">&quot;)</span><span class="synSpecial">\n</span><span class="synConstant">&quot;</span>;

<span class="synComment">// [出力結果]</span>
<span class="synComment">// pPt = (1, 0)</span>
<span class="synComment">// hPt = (0, 2)</span>

</code></pre>

<p>
確かに思ったとおりに動作している。駄目だ、ついていけない。Java とか C# とか、平気でボックス化とか言ってる言語で、この手の失敗をしないという自信が持てない。
</p>

<p>
しかも、こんな書き方もできるらしい。
</p>

<pre><code>
Point pt; <span class="synComment">// 値型をスタックに置く</span>
Point^ hPt = pt; <span class="synComment">// いきなりハンドルで受ける！！</span>

</code></pre>

<p>
C++ 的な目線で見ると、これは Point* pPt = pt; という風に見えるが、ボックス化様にそんな古い常識は通用しない。何でもアリだ。
</p>

<p>
ん、ひょっとして、new で native heap に確保したオブジェクトもボックス化様は受け入れてくれるのではないか？
</p>

<pre><code>
Point* pPt = <span class="synStatement">new</span> Point; <span class="synComment">// 値型を native heap に置く</span>
Point^ hPt = *pPt; <span class="synComment">// Point^ hPt = pt; が OK なら、これだって OK だ</span>
<span class="synStatement">delete</span> pPt;

</code></pre>

<p>
通ったぁ！ ボックス化様、万歳。...もうシラネ。
</p>

<h3>まとめ</h3>
<ul>
	<li>C++/CLI では値型にも参照型にもスタックの構文が使える</li>
	<li>スタックに置いた参照型を参照する場合は * や &amp; ではなく ^ や % を使う</li>
	<li>スタックに置いた値型を参照する場合は *, &amp;, ^, % の全てを使うことができる</li>
	<li>スタックや native heap 上のオブジェクトを ^ や % で参照すると、ボックス化によるコピーを参照するようになる</li>
</ul>]]>
            </description>
            <link>http://zakio.net/blog/2009/03/04-132423.html</link>
            <guid>http://zakio.net/blog/2009/03/04-132423.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++/CLI</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++/CLI</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ボックス化</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">値型</category>
            
            <pubDate>Wed, 04 Mar 2009 13:24:23 +0900</pubDate>
        </item>
        
        <item>
            <title>ハンドルとポインタと参照</title>
            <description>
                <![CDATA[<p>
C++ に慣れ親しんだ私は、C++/CLI のハンドルを CLI heap 用のポインタという風に理解している。native heap は new で確保してポインタへ、CLI heap は gcnew で確保してハンドルへという単純な話だ。それだけならわざわざ取り上げる必要もないが、色々と調べているうちに混乱してきたので書きながら整理してみようと思う。
</p>

<p>
まずは単純な話から。
</p>

<pre><code>
<span class="synStatement">using</span> <span class="synType">namespace</span> std;
<span class="synStatement">using</span> <span class="synType">namespace</span> System::Collections::Generic;

vector&lt;<span class="synType">int</span>&gt;* pVec = <span class="synStatement">new</span> vector&lt;<span class="synType">int</span>&gt;; <span class="synComment">// native heap を new で確保して pointer で受ける</span>
List&lt;<span class="synType">int</span>&gt;^ hList = <span class="synStatement">gcnew</span> List&lt;<span class="synType">int</span>&gt;; <span class="synComment">// CLI heap を gcnew で確保して handle で受ける</span>

<span class="synComment">// -&gt; は同じ</span>
pVec-&gt;push_back(<span class="synConstant">1</span>);
hList-&gt;Add(<span class="synConstant">1</span>);

<span class="synComment">// * も同じ</span>
(*pVec).push_back(<span class="synConstant">2</span>);
(*hList).Add(<span class="synConstant">2</span>);

<span class="synComment">// delete も同じ</span>
<span class="synStatement">delete</span> pVec;
<span class="synStatement">delete</span> hList;

</code></pre>

<p>
vector に対応するものが List という点が気持ち悪いが、まぁこれはそういうもの。大事なのは new → gcnew, * → ^ という対応の部分だ。一旦領域を確保してしまえば、後は C++ と同じように扱える。
</p>]]>
                <![CDATA[<p>
それでは参照はどうか。C++/CLI は CLI heap 用の参照としてトラッキング参照（追跡参照）というものを用意している。こちらは &amp; の代わりに % を使えばよい。
</p>

<pre><code>
vector&lt;<span class="synType">int</span>&gt;&amp; rVec = *pVec;
List&lt;<span class="synType">int</span>&gt;% tList = *hList;

cout &lt;&lt; <span class="synConstant">&quot;rVec = &quot;</span> &lt;&lt; rVec[<span class="synConstant">0</span>] &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; rVec[<span class="synConstant">1</span>] &lt;&lt; endl;
cout &lt;&lt; <span class="synConstant">&quot;tList = &quot;</span> &lt;&lt; tList[<span class="synConstant">0</span>] &lt;&lt; <span class="synConstant">&quot;, &quot;</span> &lt;&lt; tList[<span class="synConstant">1</span>] &lt;&lt; endl;

</code></pre>

<p>
ここまでは簡単だ。CLI heap を扱う場合は new の代わりに gcnew、* や &amp; の代わりに ^ や % を使えば、C++ と同じようにポインタや参照を扱うことが出来る。
</p>

<p>
ところで、C++ では実体からポインタを得る場合にも &amp; が用いられる。CLI heap 上の実体からハンドルを得る場合も、先ほどと同様に &amp; を % に置き換えればよい。
</p>

<pre><code>
vector&lt;<span class="synType">int</span>&gt;* pVec2 = &amp;rVec; <span class="synComment">// C++ では &amp; でポインタが得られる</span>
List&lt;<span class="synType">int</span>&gt;^ hList2 = %tList; <span class="synComment">// これに相当する演算子もやはり %</span>

cout &lt;&lt; (pVec == pVec2) &lt;&lt; endl; <span class="synComment">// pVec と pVec2 は同じものを指す</span>
cout &lt;&lt; (hList == hList2) &lt;&lt; endl; <span class="synComment">// hList と hList2 も同じものを指す</span>

</code></pre>

<p>
これはこれで納得できるような気もするが、参照はがしの時は (*hList).Add(2); のようにハンドルに対して ^ ではなく * を使っていたではないか。それに合わせるなら実体からハンドルを得る場合も % ではなく &amp; だと思うし、* → ^, & → % という対比を重視するならハンドルの参照はがしの方を * ではなく ^ にすべきだと思う。こういうズレが混乱を招くような気がするのだが、あまりそういった話を聞かないのは何故だろう。
</p>

<pre><code>
vector&lt;<span class="synType">int</span>&gt;&amp; rVec = *pVec;
List&lt;<span class="synType">int</span>&gt;% tList = *hList; <span class="synComment">// こうやって並べるとココの * が気になってくる</span>
vector&lt;<span class="synType">int</span>&gt;* pVec2 = &amp;rVec;
List&lt;<span class="synType">int</span>&gt;^ hList2 = %tList;

vector&lt;<span class="synType">int</span>&gt;&amp; rVec = *pVec;
List&lt;<span class="synType">int</span>&gt;% tList = ^hList; <span class="synComment">// * に対応する ^ で参照を剥がすか、</span>
vector&lt;<span class="synType">int</span>&gt;* pVec2 = &amp;rVec;
List&lt;<span class="synType">int</span>&gt;^ hList2 = %tList;

vector&lt;<span class="synType">int</span>&gt;&amp; rVec = *pVec;
List&lt;<span class="synType">int</span>&gt;% tList = *hList;
vector&lt;<span class="synType">int</span>&gt;* pVec2 = &amp;rVec;
List&lt;<span class="synType">int</span>&gt;^ hList2 = &amp;tList; <span class="synComment">// &amp; でハンドルを得てくれればスッキリしたのに......</span>

</code></pre>

<p>
まぁ、文句を言っても仕方がないので、これはこういうもんだと思うしかない。
</p>

<p>
次に、こんな関数を用意してみた。
</p>

<pre><code>
<span class="synType">void</span> Func1(vector&lt;<span class="synType">int</span>&gt;** ppVec) {
  *ppVec = <span class="synStatement">new</span> vector&lt;<span class="synType">int</span>&gt;(<span class="synConstant">10</span>);
}

<span class="synType">void</span> Func2(List&lt;<span class="synType">int</span>&gt;^^ hhList) {
  *hhList = <span class="synStatement">gcnew</span> List&lt;<span class="synType">int</span>&gt;(<span class="synConstant">10</span>);
}

</code></pre>

<p>
Func1 はポインタそのものを書き換えるために、ポインタへのポインタを引数としている。Func2 は Func1 の * を ^ に置き換えたもの。* → ^ というルールで全てうまくいくなら Func2 も問題ないはずだが、残念ながらこれはコンパイルエラーとなってしまう。
</p>

<pre><code>
error C3699: '^' : cannot use this indirection on type 'System::Collections::Generic::List<T> ^'

</code></pre>

<p>
<a href="http://www.ecma-international.org/publications/standards/Ecma-372.htm">C++/CLI の仕様書</a>にはそれらしい記述が見当たらなかったので、これが言語的に禁止されているかどうかは不明。ただ、ハンドルのハンドルを許してしまうと、ハンドルのハンドルのハンドルのハンドルの......ハンドルも合法となり、ガベージコレクションの時に悲惨なことになりそうな気はする。理由はともかく、<a href="http://msdn.microsoft.com/ja-jp/library/w4ctbshy(VS.80).aspx">C3699 の説明</a>には「^^ の代わりに ^% を使え」とあるので、コンパイルを通したければそれに従うしかない。^% は C++ 的には *&amp; に相当するので、これは「ハンドルそのものを参照渡ししなさい」という意味だ。「そりゃぁそうなんだけど･･････」と、モヤモヤしたまま書き直した以下のコードは（当然ながら）コンパイル可能。
</p>

<pre><code>
<span class="synType">void</span> Func1(vector&lt;<span class="synType">int</span>&gt;*&amp; pVec) {
  pVec = <span class="synStatement">new</span> vector&lt;<span class="synType">int</span>&gt;(<span class="synConstant">10</span>);
}

<span class="synType">void</span> Func2(List&lt;<span class="synType">int</span>&gt;^% hList) {
  hList = <span class="synStatement">gcnew</span> List&lt;<span class="synType">int</span>&gt;(<span class="synConstant">10</span>);
}

</code></pre>

<p>
ハンドルやトラッキング参照にスタック構文が加わると話がもう少しややこしくなるのだが、長くなってきたので別の機会に。
</p>

<h3>まとめ</h3>
<ul>
	<li>CLI heap は new ではなく gcnew で確保し、* ではなく ^（ハンドル）で受ける</li>
	<li>CLI heap 用の参照は &amp; ではなく %（トラッキング参照, 追跡参照）</li>
	<li>ポインタもハンドルも参照はがしは * だが、トラッキング参照からハンドルを得る場合は &amp; ではなく %</li>
	<li>^^（ハンドルのハンドル）は不可</li>
</ul>

<h3>参考文献</h3>
<ul>
	<li><a href="http://www.ecma-international.org/publications/standards/Ecma-372.htm">C++/CLI Language Specification, Standard ECMA-372</a></li>
</ul>]]>
            </description>
            <link>http://zakio.net/blog/2009/02/25-215637.html</link>
            <guid>http://zakio.net/blog/2009/02/25-215637.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">C++/CLI</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">C++/CLI</category>
            
            <pubDate>Wed, 25 Feb 2009 21:56:37 +0900</pubDate>
        </item>
        
        <item>
            <title>ソースコードを美しく</title>
            <description>
                <![CDATA[<p>
といっても、読みやすいきれいなソースコードを書きましょうといった話ではなく、blog 上でソースコードをきれいに表示したいという話。
</p>

<p>
気になったことを備忘録の感覚で書き留めていこうという趣旨で blog を始めたのだが、気になることの大半がソフトウェアに関する事なので、ソースコードを簡単にコピペできることは「めんどくさくない」運用という点においては必須の機能。
</p>

<p>
とりあえずは、以下のようなコードが普通にコピペできれば合格だ。<br />
 <br />
<span style="color:blue;">template</span> &lt;<span style="color:blue;">typename</span> T&gt;<br />
<span style="color:blue;">class</span> Hoge {<br />
&nbsp;&nbsp;&nbsp;&nbsp;T m_val;<br />
<span style="color:blue;">public</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">explicit</span> Hoge(<span style="color:blue;">const</span> T&amp; val = T()): m_val(val) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">const</span> T&amp; GetVal() <span style="color:blue;">const</span> {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span> m_val; <span style="color:green;">// 持ってる値を返すだけ。意味も無くコメントを書いているのは、一行を無理やり長くするためだったりする。</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};
</p>]]>
                <![CDATA[<p>
HTML では一部の記号をエスケープしないといけないし、キーワードを判別して色付けしてくれる訳でもないので、当然「普通にコピペ」しただけでは上のようには表示されない。上の例はとりあえず span やら &amp;amp; やらを駆使して手作業で整形したもの。これを自動でやってくれる何かがあれば、blog を備忘録として活用できる可能性が一気に上がるというわけだ。
</p>

<h3>SyntaxHighlighter</h3>

<p>
検索で真っ先にヒットしたのが <a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">SyntaxHighlighter</a> というもの。<a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter:Demo">見た感じ良さそげ</a>なので試してみようとしたのだが、Java Script で書かれているという点に引っかかってしまった。<a href="https://addons.mozilla.org/ja/firefox/addon/722">NoScript</a> を愛用している私が、ブログツールやコメントの類ならともかく、自分の blog のエントリー部分で Java Script に頼ってしまうのは何ともいえない矛盾を感じる。Java Script を OFF にしていればシンタックスハイライト無しの pre タグとして見えるような気がするので、もしそうなら許容範囲に収まっているかも知れないが、とりあえず保留。
</p>

<h3>VimColor</h3>

<p>
次に見つかったのが <a href="http://blog.drry.jp/2005/12/16/1855">VimColor プラグイン</a>というもの。これは Movable Type 用のプラグインなので、サーバ側で整形処理が完結する。よし、これだ。
</p>

<pre><code>
<span class="synType">template</span> &lt;<span class="synType">typename</span> T&gt;
<span class="synType">class</span> Hoge {
  T m_val;
<span class="synStatement">public</span>:
  <span class="synType">explicit</span> Hoge(<span class="synType">const</span> T&amp; val = T()): m_val(val) {}
  <span class="synType">const</span> T&amp; GetVal() <span class="synType">const</span> {
      <span class="synStatement">return</span> m_val; <span class="synComment">// 持ってる値を返すだけ。意味も無くコメントを書いているのは、一行を無理やり長くするためだったりする。</span>
  }
};

</code></pre>

<p>
最初のインデントがおかしいけど、概ね良好。うん、悪くないね。
</p>

<p>
......と、簡単に導入しているように見えるが、root 権限の無いレンタルサーバ上に Perl のモジュールやら vim やら（！）をインストールするのは大変な作業だった。そもそも「CPAN って何？」状態だったし、PuTTY を使ったのも初めて。
</p>

<p>
以下、参考にしたもの。
</p>

<ul>
  <li><a href="http://i-am.web777.net/2006/12/vimcolor.html">vimcolor プラグイン</a></li>
  <li><a href="http://iandeth.dyndns.org/mt/ian/archives/000623.html">一般ユーザ環境におけるCPANモジュールの使い方</a></li>
  <li><a href="http://www.hazama.nu/t2o2/archives/002696.html">さくらインターネットの共用サーバに vim をインストールする</a></li>
</ul>

<p>
また、<a href="http://wo.skr.jp/mt/2005/11/cpan.html">ここ</a>のコメント欄にあるように、SetEnv できない環境下で CGI からローカルモジュールを使う場合は use lib が必要。そのため、プラグインの頭の部分を以下のように修正して Text::VimColor モジュールのインストール先を指定する。
</p>

<pre><code>
<span class="synPreProc">use strict</span>;
<span class="synPreProc">use </span>MT;
<span class="synPreProc">use </span>MT::Template::Context;
<span class="synPreProc">use lib</span> <span class="synConstant">'/home/*****/perl/lib/perl5/site_perl'</span>;
<span class="synPreProc">use </span>Text::VimColor;

</code></pre>

<p>
私のように vim を自前でインストールした場合は、Text::VimColor にもその場所を教えてあげないといけない。
</p>

<pre><code>
<span class="synStatement">my</span> <span class="synIdentifier">$vimcolor</span> = Text::VimColor-&gt;<span class="synStatement">new</span>(<span class="synConstant">vim_command </span>=&gt; <span class="synConstant">'/home/*****/local/bin/vim'</span>, <span class="synConstant">vim_options </span>=&gt; <span class="synIdentifier">\@options</span>);

</code></pre>

<p>
また、そのままだとエラーになるので、options に -T xterm を追加する。この問題の解決には <a href="http://www.perlmonks.org/?node_id=605626">Text::VimColor in a CGI - possible?</a> が役立った。ついでに、さりげなく tabstop を 4 にしている。
</p>

<pre><code>
<span class="synStatement">my</span> <span class="synIdentifier">@options</span> = (<span class="synConstant">qw( -XZ -i NONE -u NONE -N -T xterm )</span>,
  <span class="synConstant">'+set nomodeline'</span>,
  <span class="synConstant">'+set expandtab'</span>,
  <span class="synConstant">'+set tabstop=4'</span>,
  <span class="synConstant">'+set encoding='</span> . MT::ConfigMgr-&gt;instance()-&gt;PublishCharset);

</code></pre>

<p>
ちなみに、MTEntryBody だけでなく MTEntryMore の方にも vim_color = "none" としておかないと、「続き」側で編集した内容に VimColor が適用されない。まぁ、このあたりは特に何も書かなくても気づくとは思うが、念のため。
</p>

<pre><code>
<span class="synIdentifier">&lt;$MTEntryMore vim_color=</span><span class="synConstant">&quot;none&quot;</span><span class="synIdentifier">$&gt;</span>

</code></pre>

<p>
それにしても、プラグインの導入記事にプラグイン自身が活躍するところが面白い。いい感じに続けられそうな気がするぞ。
</p>]]>
            </description>
            <link>http://zakio.net/blog/2009/02/20-015652.html</link>
            <guid>http://zakio.net/blog/2009/02/20-015652.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Movable Type</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">VimColor</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">シンタックスハイライト</category>
            
            <pubDate>Fri, 20 Feb 2009 01:56:52 +0900</pubDate>
        </item>
        
        <item>
            <title>blog あるいは備忘録</title>
            <description>
                <![CDATA[<p>とりあえずテスト。</p>

<p>こんなイイ加減なエントリーで始まるブログも珍しいと思うが、極度に飽きっぽい私にとっては、これくらいから始めた方が長続きするはず。</p>

<p>最近（に限った話ではないかも知れないが）物忘れが激しくなってきた気がするので、気になったことは記録しておいた方がいいかも、というのがブログを始めようと思った動機。ただし、記録という作業そのものに手間がかかってしまうとあっという間に終了フラグが立ってしまう。</p>

<p>そこで、ブログ界のデファクトスタンダードである（らしい） Movable Type を導入し、このあたりの「めんどくささ」を取り除いてみようという試みだが、果たしてうまくいくことやら......。</p>]]>
                
            </description>
            <link>http://zakio.net/blog/2009/02/14-215530.html</link>
            <guid>http://zakio.net/blog/2009/02/14-215530.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Movable Type</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">Movable Type</category>
            
            <pubDate>Sat, 14 Feb 2009 21:55:30 +0900</pubDate>
        </item>
        
    </channel>
</rss>
