2005年10月 2日

C++ のテンプレートでダックタイピング

Ruby や Python などの動的な言語では、ダックタイピング (duck typing) というテクニックが多用されています。

ダックタイピングは、同じインタフェースさえ備えていれば型は何でも構わない、という考え方に基づく多態 (polymorphism) の手法です。アヒルのように見えて、アヒルのように鳴くなら、アヒルに違いない、というわけです。

そして、現在最も注目を浴びている言語である C++ でもテンプレートを用いるとダックタイピングを行えます。

 

ダックタイピングを使うと、継承関係を無視して多態的にオブジェクトのメソッドを呼び出せます。たとえば、次の Ruby のコードでは、func に Duck と Foo のどちらのオブジェクトを渡しても正常に動作します。これは Duck, Foo ともに、共通のインタフェースを持つ quack メソッドを備えているためです。quack を持たないオブジェクトを渡すと実行時エラーになります。

class Duck
  def quack; puts "gaaa"; end
end

class Foo
  def quack; puts "...."; end
end

def func(ducky)
  ducky.quack
end

duck = Duck.new
foo = Foo.new
func(duck)
func(foo)

C++ では同様のコードを次のように書けます。func は template を使って「アヒルのようなオブジェクト」のリファレンスを受け取っています。quack() を持たないオブジェクトを渡すと実行時エラーではなくコンパイルエラーになるのがポイントです。

#include <iostream>
using namespace std;

struct Duck {
    void quack() const { cout << "gaaa" << endl; }
};

struct Foo {
    void quack() const { cout << "...." << endl; }
};

template <typename Ducky>
void func(const Ducky& ducky) {
    ducky.quack();
}

int main () {
    Duck duck;
    Foo foo;
    func(duck);
    func(foo);
    return 0;
}

C++ のテンプレートは相当おもしろいので Modern C++ Design を読んで勉強中です。

参考ページ