OpenGLをC++11でラップしてみんとてするなり 第5回

早速、前回(第4回)で作ったDepthTestのインスタンスを、gl::Contextのメソッド中で作成するようにしてみます。

gl/Context.h

namespace gl
{
  class Context : noncopyable<Context>
  {
    // 一部省略
  public :
    DepthTest depth_test(bool enabled)
    {
      return DepthTest(enabled) ;
    }
  } ;
}

 このコードはコンパイルできません。DepthTesterをコピー不可としているからです。
 かといってコピーを許してしまうと、RVO(関数内でのreturnされるオブジェクトの構築を、関数外で戻り値が格納される変数の構築に置き換える最適化)を行わないコンパイラでは、コンストラクタとデストラクタが複数回ずつ呼ばれてしまい、必要以上にGL関数が呼び出されます(尤も、C++11対応のコンパイラならRVOに対応しているとは思いますが、RVOはC++の仕様上ではオプションなので、頼らないことにします)。

 そこで、コピーコンストラクタは禁止したままで、ムーブコンストラクタを実装します。
 ムーブコンストラクタには、移動元のデータをそっくりそのまま引き継ぐための処理を書きます。ただ、処理を引き継いだからといって自動で移動元のデストラクタが呼ばれなくなるようになるわけではないため、デストラクタを呼ばなくするための処理も必要になるでしょう。デストラクタ以外のメソッドは(デストラクタ中から呼び出すものを除いて)呼び出されないはずなので、移動後に呼び出された際にエラーとするような処理は省略していいでしょう(プログラマーは、移動元オブジェクトを今後絶対に使わないとわかっている時しか移動を行わないはずです)。
 右辺値参照やらムーブコンストラクタについての詳しい話は第6回に入る前に行うとして、Enablerの具体的な実装は、サンプルコードのようになります。

 折角なので、http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml にある値を軒並み実装しておきました。GL_CLIP_PLANEiとGL_LIGHTiに関しては、別途ClipPlaneクラスとLightクラスの中で設定できる方がよいかと思いますので、省略してあります。