🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

8032閲覧

enumの値はコンパイル時定数?enumとconstexprの使い分け

tuyudaku

総合スコア75

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/09/26 01:24

constexprの存在を知ってからは
これならコンパイル時定数だからなるべく使っていくべきだと思い
定数を定義する場合はconstexprを中心に、使えないところではconstという感じで定数を定義してきました。

そうしているうちに、どちらにしろ定義名は付けるのだから
衝突を避けたり、型名として扱ったりしたいわけじゃないのなら
わざわざenumを使わずに、constexprの方がいいのだろうと考え出して
enumを使うことがほとんどなくなってしまいました。

ただ、本当にそうなのか...?と疑問に思い始めて
enumについて調べていたのですが
列挙宣言 - cppreference.com
このサイトに

enum name { enumerator = constexpr , enumerator = constexpr , ... }

このような記述がありました。
このenumerator = constexprという記述
つまりenumの値というのはコンパイル時定数ということなのでしょうか?
明確にenumはコンパイル時定数だという記述が書いてあるようなサイトが見つからず悩んでいるところです

もしそうなのであれば、enumをもっと活用しておくべきだったなと思っているのですが
皆さんはどういう風に定数の使い分けているのか(特にenumconstexpr
enumの使うべき場面、constexprの使うべき場面など
よろしかったら教えていただけないでしょうか?

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

このenumerator = constexprという記述
つまりenumの値というのはコンパイル時定数ということなのでしょうか?

質問者さんの疑問は、下記2つの話題が混じっているように思えます。該当サイトの表記は、[A]に対応しています。

  • [A] enum列挙子の定義では、定数式の値が要求される。
  • [B] enum列挙子の利用時に、定数式として扱われる。

[B]はかつて「enumハック(enum hack)」とよばれた技法であり、C++11 constexpr登場以前からあるコンパイル時定数を記述する古のテクニックです。static const int N = 42;のような定数定義がサポートされない古臭いコンパイラ向けのハックの一種でした。

enumハックの記述自体は今でも有効ですが、定数式が必要であればconstexprを用いるべきでしょう。


enumの使うべき場面、constexprの使うべき場面など

本来、両者は直交した機能です。プログラムの意味論上、物事の列挙(enumeration)にはenumをつかい、コンパイル時処理のサポートが必要ならconstexprを使えばよいと思います。

FYI: constexprは「コンパイル時/実行時処理の両方」をサポートしますが、C++20ではconstevalという「コンパイル時処理に限定」という機能も追加予定です。

投稿2019/09/26 03:33

編集2019/09/26 04:20
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuyudaku

2019/09/26 04:18

>該当サイトの表記は、[A]に対応しています。 なるほど、とても腑に落ちました >コンパイル時処理のサポートが必要ならconstexprを使えばよいと思います。 コンパイル時処理のサポートが必要な状況 私にはまだその状況を想像することが出来ませんが とりあえず「コンパイル時定数」ということと 出典は忘れましたが、利用することでconstよりはパフォーマンスが良くなる というのを見ました(微々たるものでしょうけど) この認識は間違っていないでしょうか? 私の中のイメージとしては constexprはメモリ上に展開されないもの 極端な話define定義と同じイメージだと考えていたのですが これも考え方の方向としては間違っていないでしょうか? 重ねての質問で申し訳ありません >constexprは「コンパイル時/実行時処理の両方」をサポートしますが コンパイル時として扱えない場合は、実行時処理になるのですね ただの定数として扱う場合はあまり気にすることな無いでしょうか
yohhoy

2019/09/26 08:18 編集

> コンパイル時処理のサポートが必要ならconstexprを使えばよい 「constexprを記述=必ずコンパイル時に処理される」では無いため、このような回りくどい書き方になっています。 > 「コンパイル時定数」ということと[...]利用することでconstよりはパフォーマンスが良くなるというのを見ました(微々たるものでしょうけど) > この認識は間違っていないでしょうか? 「constにくらべてconstexprの方が高パフォーマンス」という認識であれば、完全に誤りではないものの、大きな誤解があるように思います。 本来の意図を推測するに、「コンパイル時点で結果を計算できてしまうのであれば、実行時に毎回計算するよりは効率的である」ではないでしょうか。 constであってもコンパイル時に処理されるケースもありますし、constexprであっても実行時に処理されるケースがありえます。このあたりの仕様は非常にややこしいので、ここでは解説しきれません... > constexprはメモリ上に展開されないもの > 極端な話define定義と同じイメージだと考えていたのですが > これも考え方の方向としては間違っていないでしょうか? コンパイル時/実行時の差異を端的に表現すると、そのプログラムが「いつ」計算を行うかの違いです。 コンパイル時計算であればあなたの手元で1回だけ処理されますし、実行時計算であればユーザの動作環境上でつど計算されます。この観点では、define(プリプロセス時処理)とconstexpr(コンパイル時処理)は同じようなものです。 ただしモダンなC++プログラミングとしては、defineよりもconstexprを利用すべきですね。
yohhoy

2019/09/26 08:22 編集

>> constexprは「コンパイル時/実行時処理の両方」をサポートしますが > コンパイル時として扱えない場合は、実行時処理になるのですね > ただの定数として扱う場合はあまり気にすることな無いでしょうか そうですね。 絶対にコンパイル時定数が必要なケース(例:配列要素数)で、コンパイル時計算ができなかった場合は、単にコンパイルエラーとして報告されます。それ以外のケースでは、コンパイラは何も言わず実行時計算にフォールバックします。
tuyudaku

2019/09/26 12:07

>constであってもコンパイル時に処理されるケースもありますし 知りませんでした。 そこも意識してコーディングできると良さそうですね >コンパイル時/実行時の差異を端的に表現すると、そのプログラムが「いつ」計算を行うかの違いです。 >この観点では、define(プリプロセス時処理)とconstexpr(コンパイル時処理)は同じようなものです。 その観点での考え方が確認できただけでもとても嬉しいです コンパイル時として扱われた場合は少しはメモリ、計算処理の節約?になるかなと考えてコーディングしていたので ここが違ったらちょっと落ち込みました...w >ただしモダンなC++プログラミングとしては、defineよりもconstexprを利用すべきですね。 defineを排除すべくconstexpr、constを使っていこうとルールも定めました どうしてもマクロとしての利用が必要な場合のみで、定数としては扱わないこと という方向でやっています。 丁寧な回答ありがとうございました。 とても勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問