[解決済み] C言語の文字列の長さをコンパイル時に計算する。これは本当にconstexprなのか?
質問
コンパイル時に文字列リテラルの長さを計算しようとしています。これを行うために、私は次のコードを使用しています。
#include <cstdio>
int constexpr length(const char* str)
{
return *str ? 1 + length(str + 1) : 0;
}
int main()
{
printf("%d %d", length("abcd"), length("abcdefgh"));
}
すべてが期待通りに動作し、プログラムは4と8を表示します。clangによって生成されたアセンブリコードは、結果がコンパイル時に計算されることを示しています。
0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d"
0x100000f65: movl $0x4, %esi
0x100000f6a: movl $0x8, %edx
0x100000f6f: xorl %eax, %eax
0x100000f71: callq 0x100000f7a ; symbol stub for: printf
質問: この規格で保証されているのは
length
関数がコンパイル時に評価されることは保証されていますか?
もしこれが本当なら、コンパイル時に文字列リテラルを計算するための扉が開かれたことになります。
どのように解決するのですか?
定数式はコンパイル時に評価されることが保証されていません。私たちは、非正規の引用である
C++ 標準のドラフト
セクション
5.19
定数表現
というのは、こう書いてありますが。
[...]>[ 注意: 定数式は翻訳中に評価されることがあります。 注:定数式は翻訳中に評価されることがあります。]
結果を代入して
constexpr
変数に代入することで、コンパイル時に評価されることを確認できます。
Bjarne Stroustrup の C++11 リファレンス
というものです(
強調
):
コンパイル時に式を評価できるだけでなく ができるようにしたいです。 コンパイル時に評価されるように式を要求したい。 変数定義の前にあるconstexprがそれを行います。 (そして constを意味する)。
例えば
constexpr int len1 = length("abcd") ;
Bjarne Stroustrupは、コンパイル時の評価を保証できる場合について、次のようにまとめています。 isocppブログエントリ で、こう言っています。
[...]正しい答えは、Herbが述べたように は、標準によると、constexpr関数は、コンパイラ時または実行時に評価されるかもしれません。 定数式として使用されない限り、コンパイラ時または実行時に評価されます。 定数式として使われる場合は、コンパイル時に評価されなければならない。 コンパイル時に評価されなければならない。コンパイル時の評価を保証するためには、定数式として使うか を定数式として使うか(例えば,配列の束縛や大文字小文字の区別など),あるいは として)使うか,constexprを初期化するために使わなければなりません。私は 自尊心のあるコンパイラはこの最適化の機会を見逃すことはないでしょう。 私が最初に言ったように、コンパイラが最適化の機会を逃さないことを望みます。 は、その引数がすべて定数であれば、コンパイル時に評価されます。 式である場合、コンパイル時に評価されます。
つまり、これはコンパイル時に評価されるべき2つのケースの概要を示しています。
-
定数式が必要な場合に使用する。これは、標準規格の草稿の中で
shall be ... converted constant expression
またはshall be ... constant expression
が使用されている場合、配列バウンドなど。 -
を初期化するために使用します。
constexpr
を初期化するために使用します。
関連
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】std::stringをconstexprで使用することは可能ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] C++のSFINAE例?
-
[解決済み] C 言語の条件付きプリプロセッサディレクティブで文字列を比較する方法