久しぶりにブログ開いたら広告出てて泣いた。というわけで記事を書くことにする。
2015年7月20日にVisual Studio 2015がリリースされた。当然VC++も新しくなったわけだがそのうち新しく追加された機能を出来る限り毎日記事にしようと思う。
本日はそのpart01、constexprだ。
constexprはC++11で追加された機能で、現在のC++14では更にパワーアップしているのだが、Microsoftの脳みそが2011年から進んでないのでC++11版のconstexprを紹介する。
コンパイル時において定数式はその場で計算される。定数式とは例えば以下の様なもの。
int main(){
const int v = 1 + 2;//明らかに3
const int u = 3 * 5;//明らかに15
}
一方でコンパイル時に使える定数(以下コンパイル時定数)が存在する。定数式で初期化されているconst定数がそれ。上の例で言えばvもuもコンパイル時定数である。コンパイル時に使えるとは例えばtemplate引数に渡せる。
template<int N>struct test{
static int get(){
return N;
}
};
int main(){
const int v = 1 + 2;
const int u = test<v>::get();
}
この例ではvはコンパイル時定数なのでtemplateクラスtestの引数に渡せる。一方でstaticメンバ関数getは定数式ではないのでuはコンパイル時定数でない定数である。この場合uはtemplate引数に渡せない。
変数に対するconstexprは変数がコンパイル時定数であることを保証する指定子である。型はあくまでconstであり、constexprではない。
int hoge(){return 0;}
int main(){
constexpr int v = 0;//OK
constexpr int u = hoge();//NG
}
一方で関数に対するconstexprはその関数を定数式として扱えるようにする指定子である。constexpr関数の中身は実質的にreturn文一つでなければならない。
constexpr int hoge(){return 0;}
constexpr int fact(int n){return n==0 ? 1 : n*fact(n-1);}
int main(){
constexpr int v = 0;//OK
constexpr int u = hoge();//OK
constexpr int w = fact(5);//OK
}
return文一つといっても条件演算子が使えるので関数型言語に慣れている人なら親しみを持てるのではないだろうか。
定数式とできるのは組み込み型がまず上げられるがユーザー定義でconstexpr定数、またはconstexpr関数に使えるクラスも作ることができる。定数式に使える型をリテラル型と言う。
リテラル型には組み込み型やその配列がまず考えられるが、それらを組み合わせたユーザー定義型でリテラル型となる条件は以下のとおり。
・デストラクタがトリビアル
・次のどちらかを満たす「aggregateである」「コピーでもムーブでもないconstexprコンストラクタ、またはtemplateなコンストラクタを持つ」
・staticでないメンバ変数が全てvolatileでもないリテラル型
例えば以下の様なクラスがリテラル型となる。
struct pair{
int x_,y_;
constexpr pair(int x=0,int y=0):x_(x),y_(y){}
pair(pair const&)=default;
pair(pair&&)=default;
~pair()=default;
};
int main(){
constexpr pair p(0,1);
constexpr int u = p.x_;
constexpr int v = p.y_;
}
そういえば上のコードでわかるようにVS2015ではムーブコンストラクタもdefault宣言できるようになった。むしろ今までできなかったほうがおかしい。
リテラル型やconstexprに関する活用法はここでは書かない。様々な場所で論じられているのでそちらを参考にして欲しい。
参考ページ
中3女子でもわかる constexpr:
http://www.slideshare.net/GenyaMurakami/constexpr-10458089リテラル型クラスの条件、および「中3女子でもわかる constexpr」の訂正:
http://boleros.hateblo.jp/entry/20130718/1374155184C++11の文法と機能(C++11: Syntax and Feature):
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#basic.types余談
実はVC++のconstexprでバグとかないかのチェックとかまだしてないしもしかしたら規格に反する動作をするかもしれない。
PR