constexpr

提供: C++入門
移動: 案内検索
スポンサーリンク

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

関連項目




スポンサーリンク