const, constexpr, consteval, constinit ...
const
int * ptr1; /* pointer to int */
int const * ptr2; /* pointer to "int const" */
const int * ptr3; /* pointer to "const int" */
int * const ptr4; /* constant pointer to "int" */
const int * const ptr5; /* constant pointer to "const int" */
-
ptr1
はint
へのポインタ -
ptr2
はint const
へのポインタ- ポインタの指す先の値は
int const
なので不変
- ポインタの指す先の値は
-
ptr3
はconst int
へのポインタ- ポインタの指す先の値は
const int
なので不変
- ポインタの指す先の値は
-
ptr4
はint
への定数ポインタ- ポインタの指す先の値は
int
なので可変 - ポインタそのものは不変
- ポインタの指す先の値は
-
ptr5
はconst int
への 定数ポインタ- ポインタの指す先の値は
const int
なので不変 - ポインタそのものも不変
- ポインタの指す先の値は
定数は const <type>
, <type> const
のどちらで記述しても良いが,定数ポインタは <type>* const ptr
のように *
の後に const
を記述する.
int const
,const int
は同義なのでptr2
,ptr3
は同義
int * const ptr
の記法に従うならば const int var
より int const var
の方が自然なのかもしれない.
constexpr
constexpr auto foo(int n) -> bool {
auto var = 42;
if (n + var != 42) { var = 42 - n; }
return n + var;
}
constexpr
はコンパイル時計算する関数に付ける.
コンパイル時計算には引数が constexpr
でなければならず,そうでない場合は実行時計算される.
また関数内部で関数外部の変数を参照する場合はその変数が constexpr
でなければならず,そうでない場合はエラーとなる.
実行時定数には
const
を,コンパイル時定数にはconstexpr
を付ける
追記 (C++14での制限緩和について)
constexpr
な関数では主に以下が許可されている
- ローカル変数の宣言
- ローカル変数・非静的メンバ変数の書き換え
-
if
,switch
による条件分岐 -
for
,while
,do-while
によるループ
C++11 では
return
文しか許可されなかったが,C++14から大幅に緩和された
constexpr
な関数の中で return
文しか許されないのは C++11 までの制限ではないでしょうか
参考 : https://cpprefjp.github.io/lang/cpp14/relaxing_constraints_on_constexpr.html
知識をアップデートできていませんでした.ありがとうございます.
ご指摘を受けて修正しました.
consteval
consteval auto foo(int n) -> int {
return n * n;
}
auto main() -> int {
constexpr auto svar_1 = foo(5); /* OK */
auto dvar = 5;
constexpr auto svar_2 = foo(dynvar); /* NG */
}
consteval
は constexpr
関数と同様にコンパイル時計算する関数に付けるが,こちらはより厳密である.
constexpr
関数と同様にコンパイル時計算には引数が constexpr
でなければならないが,そうでない場合はエラーとなる.
constinit
/* global */
constinit auto pi = 3.14;
/* local */
auto main() -> int {
static constinit auto phi = 1.618;
}
constinit
はコンパイル時静的初期化する定数に付ける.
静的 なのでローカルで宣言するなら static
を付ける必要がある.