constexprを初めから理解する
- C++ではコンパイル時定数と実行時定数がある
- コンパイル時定数はconst修飾された整数型とenumのみ
- 配列のサイズ、テンプレート引数に指定できるのはコンパイル時定数のみ
- const修飾子は型が整数型ならコンパイル時定数になり、非整数型なら実行時定数になる
- constexpr指定すると明示的にコンパイル時定数である事を示す
constexprを使う時の考え方
- 自明な定数値を返す関数に付加する
constexpr実装のコツ
- ローカル変数は実装用関数の引数にすると良い
リテラルクラス
lvalue/rvalue
const class object
const修飾子を付けてインスタンス化したらuninitialized constのエラーが出た。
- 参考:https://stackoverflow.com/questions/4674332/declaring-a-const-instance-of-a-class
- POD はデフォルトコンストラクタを持たないので初期化されない。
- で、classでデフォルトコンストラクタが無い場合はconstで実行時定数にした所で永遠に値をセットできないのでuninitialized constのエラーが出る。
- 回避方法はデフォルトコンストラクタを定義
して非PODにするしかない。
classでコンストラクタを定義しない場合のコンストラクタってどうなるんだっけ?
- この時に発動するコンストラクタがデフォルトコンストラクタだと思っていたが…。
- 引数の無いコンストラクタをデフォルトコンストラクタと言う。
- ユーザー定義されない場合、かつコード無いでコールされた時はコンパイラが暗黙的にデフォルトコンストラクタを定義する。
- 引数があるコンストラクタを定義した場合はコンパイラによるデフォルトコンストラクタの生成は抑制される。Hoge() = default; と記述するとコンパイラによるデフォルトコンストラクタの生成を強制できる。
Hoge() = default; を記述しない場合は非ユーザー定義デフォルトコンストラクタが存在しないため trivial でなくなるので注意が必要。
参考:https://ja.cppreference.com/w/cpp/language/default_constructor
constexpr コンストラクタを持つクラスって…
- constexpr Hoge hoge = Hoge(); // Hoge() は constexpr コンストラク
- 非 static member がある場合は constexpr コンストラクタの定義はできないで正しいよね?
- それができるんですよね。下記の様な事ができる。
要は class 型の変数定義だろうがコンパイル時にできる静的な処理であれば constexpr で記述できる、コンパイル時のみの話なのでオブジェクトのアドレスは当然取れない点に注意。
1234567891011121314151617class Kitty{public:constexpr Kitty(int a) : m_Data(a){}// const メンバ関数にするのを忘れずに!constexpr int GetData() const { return m_Data; };private:int m_Data;};int main(){constexpr Kitty kitty(1);// 静的にアサートできる。static_assert(kitty.GetData() == 1);return 0;}
- それができるんですよね。下記の様な事ができる。
コメントを残す