「constexpr」の版間の差分
提供: C++入門
行32: | 行32: | ||
* constは、初期化しが定数式の場合、定数式になる。 | * constは、初期化しが定数式の場合、定数式になる。 | ||
* それ以外の場合は、const修飾をしているだけ。 | * それ以外の場合は、const修飾をしているだけ。 | ||
+ | |||
+ | == constとconstexprの例 == | ||
+ | |||
+ | 定数x(X.n)のメンバを配列のサイズに指定しています。 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | struct X { int n; }; | ||
+ | const X x = {123}; | ||
+ | int a[x.n] = { 1 }; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | [[clang++]](3.3,3.4)や[[g++]](4.6,4.7)では、以下のエラーとなります。 | ||
+ | ;clagn++(clang++33, clang++34): error: variable-sized object may not be initialized | ||
+ | ;g++(g++46,g++47): error: variable-sized object 'a' may not be initialized | ||
+ | |||
+ | なお、g++49(g++ 4.9.1 20140507)では、何事もなく、コンパイルされます。 | ||
+ | |||
+ | 固定長配列のサイズは、コンパイル時定数のみが指定できます。 | ||
+ | X は、定数ではありますが、変数 x は、実行時定数です。 | ||
+ | |||
+ | これを解決するには、Xに[[constexpr]]指定し、明示的にコンパイル時定数として扱います。 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | struct X { int n; }; | ||
+ | constexpr X x = {123}; | ||
+ | int a[x.n] = { 1 }; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === const1.cpp === | ||
+ | これは、ダメな例です。constではなく、constexprを使用するべきです。 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | /* | ||
+ | * constexpr1.cpp | ||
+ | * Copyright (C) 2014 kaoru <kaoru@bsd> | ||
+ | */ | ||
+ | #include <iostream> | ||
+ | using namespace std; | ||
+ | |||
+ | int | ||
+ | main(int argc, char const* argv[]) | ||
+ | { | ||
+ | struct X { int n; }; | ||
+ | const X x = {123}; | ||
+ | int a[x.n] = { 1 }; | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === コンパイル === | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | $ c++ const1.cpp | ||
+ | const1.cpp:13:8: error: variable-sized object may not be initialized | ||
+ | int a[x.n] = { 1 }; | ||
+ | ^~~ | ||
+ | 1 error generated. | ||
+ | </syntaxhighlight> | ||
+ | === constexpr1.cpp === | ||
+ | これは、const1.cppに対する、正しい解です。 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | /* | ||
+ | * constexpr1.cpp | ||
+ | * Copyright (C) 2014 kaoru <kaoru@bsd> | ||
+ | */ | ||
+ | #include <iostream> | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | int | ||
+ | main(int argc, char const* argv[]) | ||
+ | { | ||
+ | struct X { int n; }; | ||
+ | constexpr X x = {123}; | ||
+ | int a[x.n] = { 1 }; | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | === コンパイル === | ||
+ | constとは違い、constexprでは、エラーになりません。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | $ c++ -std=c++11 constexpr1.cpp | ||
+ | </syntaxhighlight> | ||
== 関連項目 == | == 関連項目 == | ||
* [[C++11]] | * [[C++11]] | ||
* [[C++14]] | * [[C++14]] | ||
− | <!-- vim: filetype=mediawiki --> | + | <!-- vim: filetype=mediawiki |
+ | --> |
2014年8月16日 (土) 20:12時点における最新版
constexpr とは、C++11で導入された指定子で、変数の定義、関数や関数テンプレートの宣言、リテラル型の静的データメンバの宣言に適用するものです。constexpr宣言された変数は、コンパイル時に定数になります。constexpr宣言された関数やコンストラクタは、コンパイル時と実行時に呼び出せます。リテラル型のオブジェクトは、コンパイル時に定数になります。
読み方
- constexpr
- こんすと いーえっくすぴーあーる
目次
概要
constexpr とは、C++11で導入された指定子で、変数の定義、関数や関数テンプレートの宣言、リテラル型の静的データメンバの宣言に適用するものです。
constexpr宣言された変数は、コンパイル時に定数になります。
constexpr int zero = 0; // constexpr 変数 auto x = foo<int, zero>; // テンプレートに渡すことが可能
constexpr宣言された関数やコンストラクタは、コンパイル時と実行時に呼び出せます。
constexpr int zero(){return 0;} // constexpr関数 constexpr int cc_time_zero = zero(); // コンパイル時に呼び出し int runtime_zero = zero(); // 実行時に呼び出し
リテラル型のオブジェクトは、コンパイル時に定数になります。
struct literal_type{}; constexpr auto literal = literal{};
constとの違い
- constは、定数としてオブジェクトを宣言する。これは、オブジェクトが変更されず、値が変わらないことを意味する。コンパイラは、最適化に利用できる。初期化されたあとに、プログラマが誤って上書きしてはいけないオブジェクトを変更するのを防止できる。
- constは、コンパイル時に定数ではなくてもよい。
- constは、初期化しが定数式の場合、定数式になる。
- それ以外の場合は、const修飾をしているだけ。
constとconstexprの例
定数x(X.n)のメンバを配列のサイズに指定しています。
struct X { int n; }; const X x = {123}; int a[x.n] = { 1 };
clang++(3.3,3.4)やg++(4.6,4.7)では、以下のエラーとなります。
- clagn++(clang++33, clang++34)
- error: variable-sized object may not be initialized
- g++(g++46,g++47)
- error: variable-sized object 'a' may not be initialized
なお、g++49(g++ 4.9.1 20140507)では、何事もなく、コンパイルされます。
固定長配列のサイズは、コンパイル時定数のみが指定できます。 X は、定数ではありますが、変数 x は、実行時定数です。
これを解決するには、Xにconstexpr指定し、明示的にコンパイル時定数として扱います。
struct X { int n; }; constexpr X x = {123}; int a[x.n] = { 1 };
const1.cpp
これは、ダメな例です。constではなく、constexprを使用するべきです。
/* * constexpr1.cpp * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <iostream> using namespace std; int main(int argc, char const* argv[]) { struct X { int n; }; const X x = {123}; int a[x.n] = { 1 }; return 0; }
コンパイル
$ c++ const1.cpp const1.cpp:13:8: error: variable-sized object may not be initialized int a[x.n] = { 1 }; ^~~ 1 error generated.
constexpr1.cpp
これは、const1.cppに対する、正しい解です。
/* * constexpr1.cpp * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <iostream> using namespace std; int main(int argc, char const* argv[]) { struct X { int n; }; constexpr X x = {123}; int a[x.n] = { 1 }; return 0; }
コンパイル
constとは違い、constexprでは、エラーになりません。
$ c++ -std=c++11 constexpr1.cpp