2014-10-01

C++14の新機能: 変数テンプレート

C++14に追加された新機能、変数テンプレートは、名前の通り、変数をテンプレート宣言する機能である。

変数テンプレートのコードをいきなり読むと、あるいは混乱するかもしれないので、変数テンプレートについて解説する前に、まず、テンプレートについて解説しようと思う。

C++には、関数というものがある。関数には、具体的な型を書く必要がある。

int min_int( int a, int b )
{
    return a < b ? a : b ;
}

double min_double( double a, double b )
{
    return a < b ? a : b ;
}

これをみると、型以外は、同一のコードである。もし、型を引数に取ることができれば、コピーコンストラクター、operator <, デストラクターのような操作ができるすべての型に対して、共通のコードで対応できることになる。そのために、C++には関数テンプレートがある。

template < typename T >
T min( T const & a, T const & b )
{
    return a < b ? a : b ;
}

また、C++には、クラスというものがある。クラスには、具体的な型を書く必要がある。

class linked_list_int
{
    linked_list_int * next ;
    linked_list_int * prev ;
    int value ;
} ;

class linked_list_double
{
    linked_list_double * next ;
    linked_list_double * prev ;
    double data ;
} ;

関数の場合と同じように、型以外は、同一のコードである。関数テンプレートと同じように、クラステンプレートは、型を引数に取り、コードの共通化を行える。

template < typename T >
class linked_list
{
    linked_list * next ;
    linked_list * prev ;
    T data ;
}

いまさら何を初歩的なことを解説しているのかと思うかもしれないが、テンプレートは型を引数化するということがわかったことと思う。

ところで、C++には変数というものがある。変数には、具体的な型を書く必要がある。

constexpr int pi_int = 3 ;
constexpr double pi_double = 3.141592 ;

これを見ると、型以外は共通化できる。C++14の変数テンプレートは、変数にテンプレート宣言ができる。

template < typename T >
constexpr T pi = static_cast<T>(3.141592) ;

int x = pi<int> ;
double y = pi<double> ;

なぜ関数テンプレートではダメなのか。関数テンプレートでもいいのだが、文法上、余計な関数呼び出し式()が必要だ。

template < typename T >
constexpr T pi() { return static_cast<T>(3.141592) ; }

int x = pi<int>() ;
double y = pi<double>() ;

プログラマーは冗長な文法を嫌うものなので、変数テンプレートが導入された。

ちなみに、変数テンプレートには、かなり有益な使い方がある。既存の値を返すtype traitsは、valueという名前のstaticデータメンバーを使っていた。

bool b = std::is_pointer<T>::value ;

変数テンプレートを使えば、以下のようにラップすることができる。

template < typename T >
constexpr bool is_pointer_v = is_pointer<T>::value ;

bool b = is_pointer_v<T> ;

C++14では、標準ライブラリに、このようにして既存のtype traitsをラップする_v版が入った。

なおこの機能はGCC 5とClang 3.4で実装されている。

Clang - C++1z, C++14, C++11 and C++98 Status

C++1y/C++14 Support in GCC - GNU Project - Free Software Foundation (FSF)

See Also:

本の虫: C++14の新機能: 2進数リテラル

本の虫: C++14の新機能: decltype(auto)

本の虫: C++14の新機能: 関数の戻り値の型推定

本の虫: C++14の新機能: 初期化lambdaキャプチャー

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

どうやら、いつの間にかドワンゴに入社して7ヶ月が経過しているようだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2 comments:

Anonymous said...

template <typename T> struct pai;は template <template <typename T> class C> のCで受けて変数化できますが、変数テンプレート template <typename T > constexpr T pi; のpiは変数化できますか?

Anonymous said...

hoge_v版は存在意義は大変いいですが、名前がダサいです。どうにかなりませんかねー。