2012-03-03

クラステンプレートとエイリアステンプレートの違い

C++11では、新しくエイリアス宣言をテンプレート化できる。これを、エイリアステンプレートと呼ぶ。エイリアステンプレートは、エイリアス宣言をテンプレート化するのだから、簡単なメタ関数ならエイリアステンプレートだけで実装できるし、また、クラステンプレートを利用したメタ関数のラッパーとしても使える。

template < typename T >
using add_pointer = typename std::add_pointer< T >::type ;

template < typename T >
void f( T )
{
    typename std::add_pointer<T>::type p1 = nullptr ;
    add_pointer<T> p2 = nullptr ;
}

また、メタ関数にかぎらず、広くクラステンプレートをラップする目的にも使える。

template <class T, class Allocator = std::allocator<T> >
using vector = std::vector< T, Allocator > ;

template < typename T >
void f( T )
{
    std::vector<T> v ; // これは簡単
    typename std::vector<T>::iterator iter = v.begin() ; // なんじゃこりゃ?
    vector<T>::iterator iter = v.begin() ; // typenameなんて必要なし!
}

こうしてみると、エイリアステンプレートのほうがメタ関数としてはるかに使いやすく感じる。余計なtypenameやら::typeやらが必要ないのだ。なぜ標準ライブラリはエイリアステンプレートを使わないのか。それには、TR1の設計段階では、エイリアステンプレートがッ規格上存在しなかったこともあろう。しかし、もうひとつ理由がある。ユーザーが特殊化を追加できないのだ。なぜならば、エイリアステンプレートには特殊化や部分的特殊化が存在しないからだ。ユーザー定義型に依存する型は、条件を満たせば、ユーザーが自由に特殊化を追加できる。それがクラスや関数のテンプレートの強みなのに、それができない。

これは、もし規格がエイリアステンプレートを使い、その実装方法を未規定にしていれば、ユーザーの特殊化を防ぐことができるという副次的な利点もある。C++11では、そのようなライブラリは入っていないのだが。

それに、規格はいつでも、ユーザーによる特殊化を、文面により明示的に禁止できる。だから、その目的でエイリアステンプレートを使う必要もない。

No comments: