-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathconstexpr.html
More file actions
433 lines (366 loc) · 36.4 KB
/
constexpr.html
File metadata and controls
433 lines (366 loc) · 36.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<!doctype html>
<html class="cpprefjp" lang="ja" itemscope="" itemtype="http://schema.org/WebPage">
<head>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NXNBNVBTJS"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-NXNBNVBTJS');
</script>
<meta charset="UTF-8">
<title>constexpr [N2235] - cpprefjp C++日本語リファレンス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="keywords" content="
C++,標準ライブラリ,リファレンス,ドキュメント,STL,std,cpp11
">
<meta name="title" content="constexpr [N2235] - cpprefjp C++日本語リファレンス" />
<meta itemprop="name" content="constexpr [N2235] - cpprefjp C++日本語リファレンス" />
<meta property="og:title" content="constexpr [N2235] - cpprefjp C++日本語リファレンス" />
<meta property="og:url" content="https://cpprefjp.github.io/lang/cpp11/constexpr.html" />
<meta property="og:site_name" content="cpprefjp - C++日本語リファレンス" />
<meta property="og:type" content="article" />
<meta property="og:description" content="`constexpr`は、汎用的に定数式を表現するための機能である。" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="constexpr [N2235] - cpprefjp C++日本語リファレンス" />
<meta name="twitter:url" content="https://cpprefjp.github.io/lang/cpp11/constexpr.html" />
<meta name="twitter:description" content="`constexpr`は、汎用的に定数式を表現するための機能である。" />
<link rel="alternate" type="application/atom+xml" title="Atom" href="https://cpprefjp.github.io/rss.xml" />
<link rel="apple-touch-icon" sizes="180x180" href="../../static/favicons/apple-touch-icon.png?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95">
<link rel="icon" type="image/png" sizes="32x32" href="../../static/favicons/favicon-32x32.png?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95">
<link rel="icon" type="image/png" sizes="16x16" href="../../static/favicons/favicon-16x16.png?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95">
<link rel="manifest" href="../../manifest.json?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95">
<meta name="theme-color" content="#f5f8fc">
<link rel="stylesheet" href="../../static/pygments/default.css?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95">
<!-- <link rel="stylesheet" href="../../static/css/root.css"> -->
<link href="../../static/kunai/css/kunai-stage-0.css?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-1.css?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-2.css?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-3.css?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95" rel="stylesheet">
<script type="text/javascript" src="../../static/kunai/js/kunai-vendor.js?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95"></script>
<script type="text/javascript" src="../../static/kunai/js/kunai.js?cachebust=be86fa2321ebe02b6955b61b98b778e377bcbf95"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var kn = new Kunai;
kn.cpprefjp();
});
</script>
</head>
<body>
<header data-kunai-mdinfo="{"meta": {"cpp": ["cpp11"]}, "sources": [{"id": "e5d910f16bf9f9b9462d24adeaf37bd99e93927e", "source": "#include <cassert>\n\nconstexpr int square(int x)\n{\n return x * x;\n}\n\nint main()\n{\n constexpr int compile_time_result = square(3);\n static_assert(compile_time_result == 9, \"result must be 9\");\n\n int runtime_result = square(3);\n assert(runtime_result == 9);\n}\n"}, {"id": "1442b94723e770c24d05c0b0af53c0f4f1a7c8ed", "source": "constexpr int min(int a, int b)\n{\n // \u6761\u4ef6\u5206\u5c90\u306b\u306f\u6761\u4ef6\u6f14\u7b97\u5b50?:\u3092\u4f7f\u7528\u3059\u308b\n return a < b ? a : b;\n}\n\nconstexpr int factorial(int n)\n{\n // \u30eb\u30fc\u30d7\u306b\u306f\u518d\u5e30\u3092\u4f7f\u7528\u3059\u308b\n return n == 0 ? 1 : n * factorial(n - 1);\n}\n\nint main()\n{\n constexpr int min_val = min(2, 3);\n static_assert(min_val == 2, \"result must be 2\");\n\n constexpr int factorial_val = factorial(5);\n static_assert(factorial_val == 120, \"result muse be 120\");\n}\n"}, {"id": "23d4aa34b768c848f1b0471ce75d97a00d75dcc1", "source": "class Integer {\n int value_;\npublic:\n constexpr Integer(int value)\n : value_(value) {}\n\n constexpr int get() const\n { return value_; }\n};\n\nint main()\n{\n constexpr Integer x = 3;\n static_assert(x.get() == 3, \"x value must be 3\");\n}\n"}], "page_id": ["lang", "cpp11", "constexpr"]}">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../index.html">
<div class="title-wrapper clearfix">
<div class="title">cpprefjp - C++日本語リファレンス</div>
</div>
</a>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<div class="google-search">
<script>
(function() {
var cx = '013316413321391058734:ji_u66hl7hq';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<div class="gcse-search"></div>
</div>
</li>
<li>
<a href="https://github.com/cpprefjp/site">GitHub Project</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main id="main" role="main">
<div class="container-fluid">
<div class="row">
<div class="col-sm-9 col-sm-push-3" itemscope itemtype="http://schema.org/Article">
<div class="row">
<div class="col-sm-12 google-search-result">
<gcse:searchresults></gcse:searchresults>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-header">
<ol class="breadcrumb">
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../index.html" itemprop="url">
<i class="fa fa-fw fa-home"></i>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../lang.html" itemprop="url">
<span itemprop="name">言語機能</span>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../lang/cpp11.html" itemprop="url">
<span itemprop="name">C++11</span>
</a>
</span>
</li>
<li class="active" itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<span itemprop="name">constexpr [N2235]</span>
</span>
</li>
</ol>
<div class="crsearch"></div>
</div>
</div>
<div class="row">
<div class="col-sm-12 edit-button">
<p class="text-right"><small>
最終更新日時(UTC):
<span itemprop="datePublished" content="2025-05-13T08:20:39">
2025年05月13日 08時20分39秒
</span>
<br/>
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Akira Takahashi</span>
</span>
が更新
</small></p>
<p class="text-right">
<a class="history" target="_blank" href="https://github.com/cpprefjp/site/commits/master/lang/cpp11/constexpr.md">
<span class="fa fa-fw fa-clock-o fa-flip-horizontal"></span>履歴
</a>
<a class="edit" target="_blank" href="https://github.com/cpprefjp/site/edit/master/lang/cpp11/constexpr.md">
<span class="fa fa-fw fa-pencil"></span>編集
</a>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-body">
<h1 itemprop="name"><span class="token">constexpr [N2235]</span><span class="cpp cpp11" title="C++11で追加">(C++11)</span></h1>
<div itemprop="articleBody"><p></p>
<p>このページはC++11に採用された言語機能の変更を解説しています。</p>
<p>のちのC++規格でさらに変更される場合があるため<a href="#relative-page">関連項目</a>を参照してください。</p>
<p></p>
<h2>概要</h2>
<p><code>constexpr</code>は、汎用的に定数式を表現するための機能である。</p>
<p><code>constexpr</code>は、「constant expression (定数式)」の略語である。</p>
<p>この機能を使用することで、コンパイル時に値が決定する定数、コンパイル時に実行される関数、コンパイル時にリテラルとして振る舞うクラスを定義できる。</p>
<p>定数式の例として、パラメータの値を2乗して返す関数<code>square()</code>は、以下のように記述する:</p>
<p><div class="yata" id="e5d910f16bf9f9b9462d24adeaf37bd99e93927e"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/cassert.html"><cassert></a></span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">square</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">compile_time_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">square</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="w"> </span><span class="k">static_assert</span><span class="p">(</span><span class="n">compile_time_result</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="s">"result must be 9"</span><span class="p">);</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">runtime_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">square</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="w"> </span><span class="n"><a href="../../reference/cassert/assert.html">assert</a></span><span class="p">(</span><span class="n">runtime_result</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">9</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<p>関数<code>square()</code>の先頭に<code>constexpr</code>キーワードを付けることで、その関数は、コンパイル時と実行時、両方で呼び出せる関数となる。</p>
<p><code>constexpr</code>関数がコンパイル時に呼び出されるか、実行時に呼び出されるかは、その関数の結果を受け取る、左辺によって決定される。引数が定数でかつ、左辺が<code>constexpr</code>修飾された変数であれば、右辺の関数はコンパイル時に呼び出される。そうでなければ、関数は実行時に呼び出される。</p>
<p><code>constexpr</code>変数は、書き換えることができない定数となる。</p>
<p><code>constexpr</code>関数もまた、その内部で変数の書き換えはできず、<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>の型を<code>void</code>にすることもできない。変数の書き換えをせずに、計算した結果を返す必要がある。また、<code>constexpr</code>関数には、その本体において、<code>return</code>文ひとつのみで処理を行わなければならない、という制限がある。そのため、条件分岐には<code>if</code>文の代わりに条件演算子を、ループには<code>while</code>文や<code>for</code>文の代わりに再帰を使用する必要がある。</p>
<p><div class="yata" id="1442b94723e770c24d05c0b0af53c0f4f1a7c8ed"><div class="codehilite"><pre><span></span><code><span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">min</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="c1">// 条件分岐には条件演算子?:を使用する</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">factorial</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="c1">// ループには再帰を使用する</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">factorial</span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">min_val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">min</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">);</span>
<span class="w"> </span><span class="k">static_assert</span><span class="p">(</span><span class="n">min_val</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="s">"result must be 2"</span><span class="p">);</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">factorial_val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">factorial</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span>
<span class="w"> </span><span class="k">static_assert</span><span class="p">(</span><span class="n">factorial_val</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">120</span><span class="p">,</span><span class="w"> </span><span class="s">"result muse be 120"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<p><code>constexpr</code>にできる変数の型は、<a href="../../reference/type_traits/is_literal_type.html">リテラル型</a>に分類される必要がある。これには、整数型、浮動小数点数、リテラル型の配列、リテラル型のみをメンバ変数として持つクラスなどが含まれる。</p>
<p><a class="cpprefjp-defined-word" data-desc="プログラム定義。ユーザー(プログラマ)によって定義されること(標準ライブラリで定義されるものを除く)">ユーザー定義</a>のクラスで、コンストラクタを定義する場合には、<code>constexpr</code>をコンストラクタの宣言に付ける。メンバ関数も、コンパイル時に呼び出す必要がある場合には、<code>constexpr</code>修飾する。この時C++14でも<a class="cpprefjp-defined-word" data-desc="プログラムが文法規則・診断対象の意味規則・単一定義規則を満たすこと" href="../../implementation-compliance.html#dfn-well-formed">適格</a>なコードであるためには<code>const</code>メンバ関数である必要がある。メンバ変数の宣言に<code>constexpr</code>を付ける必要はない。</p>
<p><div class="yata" id="23d4aa34b768c848f1b0471ce75d97a00d75dcc1"><div class="codehilite"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">Integer</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">value_</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="p">)</span>
<span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">value_</span><span class="p">(</span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">get</span><span class="p">()</span><span class="w"> </span><span class="k">const</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">value_</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>
<span class="w"> </span><span class="k">static_assert</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">get</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="s">"x value must be 3"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h2>仕様</h2>
<h3>constexpr関数</h3>
<ul>
<li><code>constexpr</code>関数の<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>の型、およびパラメータの型は、<a href="../../reference/type_traits/is_literal_type.html">リテラル型</a>でなければならない</li>
<li><code>constexpr</code>関数の<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>の型、およびパラメータの型は、非<code>const</code>参照にはできない</li>
<li><code>constexpr</code>関数の本体は、以下の要素だけを含むことができる:<ul>
<li>ヌル文</li>
<li><code>static_assert</code>宣言</li>
<li>型の別名定義</li>
<li>using宣言と、usingディレクティブ</li>
<li>唯一の<code>return</code>文</li>
</ul>
</li>
<li><code>constexpr</code>関数は暗黙的にインラインとなる</li>
<li><code>constexpr</code>関数を再帰的に呼び出せる深さは、512回以上であることが、コンパイラに推奨される</li>
<li><code>constexpr</code>関数は数学的に結果が定義された計算式、および結果が値の表現範囲内である計算式を記述できる<ul>
<li>つまり、整数をゼロ割りした場合は、プログラムは<a class="cpprefjp-defined-word" data-desc="プログラムが適格でないこと。コンパイルエラーなどになる" href="../../implementation-compliance.html#dfn-ill-formed">不適格</a>となる</li>
</ul>
</li>
<li><code>main()</code>関数は、<code>constexpr</code>関数として定義できない</li>
<li><code>throw</code>文は書けるが、それがコンパイル時に評価された場合には、プログラムは<a class="cpprefjp-defined-word" data-desc="プログラムが適格でないこと。コンパイルエラーなどになる" href="../../implementation-compliance.html#dfn-ill-formed">不適格</a>となる。</li>
</ul>
<p><div class="codehilite"><pre><span></span><code><span class="c1">// コンパイル時にtrueを渡すと、コンパイルエラーになる</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">bool</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="mi">-1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
</code></pre></div>
</p>
<h3>constexpr変数として使用する<a class="cpprefjp-defined-word" data-desc="プログラム定義。ユーザー(プログラマ)によって定義されること(標準ライブラリで定義されるものを除く)">ユーザー定義</a>クラス</h3>
<ul>
<li>コンストラクタを明示的に定義する場合には、コンストラクタを<code>constexpr</code>修飾する</li>
<li>暗黙的に定義されるコンストラクタは、自動的に<code>constexpr</code>修飾される</li>
<li><code>constexpr</code>コンストラクタのパラメータの型は、<a href="../../reference/type_traits/is_literal_type.html">リテラル型</a>でなければならない。</li>
<li><code>constexpr</code>コンストラクタには、関数<code>try</code>ブロックは使用できない</li>
<li><code>constexpr</code>コンストラクタの本体は、空でなければならない</li>
<li>仮想基底クラスを持ってはならない</li>
<li>基底クラス、および非静的メンバ変数は、メンバ初期化子を使用して初期化しなければならない</li>
</ul>
<h3>constexprメンバ関数</h3>
<ul>
<li><code>constexpr</code>メンバ関数は自動的に<code>const</code>修飾され、明示的な<code>const</code>修飾はできない</li>
<li>仮想関数は、<code>constexpr</code>関数として定義できない</li>
</ul>
<h2>備考</h2>
<h3>浮動小数点数演算での注意</h3>
<p><code>constexpr</code>関数での浮動小数点数は、コンパイル時に実行するとコンパイル環境で計算が行われ、実行時に実行すると実行環境で計算が行われる。これによって、コンパイル時と実行時で、結果が異なる可能性がある。</p>
<h3>コンパイル時と実行時で、統一したエラー報告</h3>
<p><code>constexpr</code>関数では、コンパイル時にはエラー報告に<code>static_assert</code>、実行時には<code>throw</code>文や<code>assert()</code>関数マクロなどを使用する必要があり、標準機能の範囲内では、コンパイル時と実行時で、エラー報告を統一的に行うことが難しい。</p>
<p>そういった問題を解決するために、ユーザーコミュニティで、エラー報告を統一的に行う仕組みが作られている。ここでは、その問題に取り組んでいる場所へのリンクを記載する。</p>
<ul>
<li><a href="http://boleros.hateblo.jp/entry/20130319/1363719366" target="_blank">コンパイル時/実行時両用アサート - ボレロ村上 - ENiyGmaA Code</a></li>
</ul>
<h3>グローバル変数の初期化順</h3>
<p>並行プログラミングについて考えよう。スレッド間の排他処理を行うミューテックスをグローバル変数に保持したとき、ミューテックスの初期化が、スレッドの開始よりも必ず先に行われてほしい。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">extern</span><span class="w"> </span><span class="n"><a href="../../reference/mutex/mutex.html">std::mutex</a></span><span class="w"> </span><span class="n">m</span><span class="p">;</span>
<span class="n"><a href="../../reference/thread/thread.html">std::thread</a></span><span class="w"> </span><span class="n">t1</span><span class="p">{</span><span class="n">job1</span><span class="p">};</span>
<span class="n"><a href="../../reference/thread/thread.html">std::thread</a></span><span class="w"> </span><span class="n">t2</span><span class="p">{</span><span class="n">job2</span><span class="p">};</span>
</code></pre></div>
</p>
<p>そんな状況のために、<a href="../../reference/mutex/mutex/op_constructor.html"><code>std::mutex</code>クラスのデフォルトコンストラクタ</a>には、<code>constexpr</code>修飾が行われている。そうすることで、その型の非ローカル変数を作ったときに、その変数は他の任意のスレッド開始よりも先に行われることが保証される。</p>
<ul>
<li><a href="https://zakkas783-blog-blog.tumblr.com/post/25490513807/constant-initialization" target="_blank">雑貨's tumblr - Constant Initialization</a></li>
<li><a href="http://d.hatena.ne.jp/yohhoy/20120621/p1" target="_blank"><code>mutex</code>のconstexprコンストラクタ</a></li>
</ul>
<h3>文字列処理</h3>
<p><code>constexpr</code>では、<code>new</code>演算子や<code>malloc()</code>関数が使用できないために、可変長の配列や文字列を扱うことが難しい。</p>
<p>C++11段階の標準ライブラリでも、そのような機能は標準では提供されていない。</p>
<p>こういった問題を解決するために、ユーザーコミュニティでそのような機能が作られている。ここでは、その問題に取り組んでいる場所へのリンクを記載する。</p>
<ul>
<li><a href="http://boleros.hateblo.jp/entry/20110926/1318115291" target="_blank">Sprout.String - constexpr 文字列クラス - ボレロ村上 - ENiyGmaA Code</a></li>
</ul>
<p><code>constexpr</code>で文字列が扱えることにより、<code>printf()</code>のフォーマット文字列や、正規表現の間違いをコンパイル時に検出することができるようになる。</p>
<h3>コンパイル時再帰回数</h3>
<p>コンパイラによっては、コンパイルオプションでコンパイル時における<code>constexpr</code>関数の再帰回数の上限を設定できる。</p>
<p>GCCとClangでは、<code>-fconstexpr-depth=</code>オプションで設定できる:</p>
<p><pre><code>g++ main.cpp -fconstexpr-depth=1024
</code></pre></p>
<p>Visual C++ 2015では、<code>/constexpr:depth</code>オプションで設定できる:</p>
<p><pre><code>cl.exe /constexpr:depth1024 main.cpp
</code></pre></p>
<p>ここの<code>1024</code>を任意の値に変更することで、再帰回数の上限を設定できる。</p>
<p>GCC 5.2、Clang 3.7、Visual C++ 2015時点で、3つともデフォルトは512回。</p>
<h2>この機能が必要になった背景・経緯</h2>
<p><code>constexpr</code>の主な目的は、数値型のプロパティを取得するクラス<code><a href="../../reference/limits/numeric_limits.html">std::numeric_limits</a></code>の、プロパティ取得の関数を定数式にすることである。</p>
<p>たとえば、<code><a href="../../reference/limits/numeric_limits.html">std::numeric_limits</a></code>の<code><a href="../../reference/limits/numeric_limits/max.html">max()</a></code>静的メンバ関数は、<code>int</code>型に対しては<code><a href="../../reference/climits/int_max.html">INT_MAX</a></code>マクロの値を返すだけであるが、それが関数であるために、<code><a href="../../reference/climits/int_max.html">INT_MAX</a></code>マクロと違って定数として扱えない、という問題があった。抽象化された機能を使うより、抽象化されていない機能の方がよい、というのは、改善すべき事態だった。そのため、関数を静的に評価する仕組みが必要とされた。</p>
<p>また、<code>constexpr</code>は、値を計算するテンプレートメタプログラムを置き換えて使用できる。テンプレートメタプログラミングでは、非型テンプレートパラメータによって整数型の値をコンパイル時に計算することはできた。しかし、浮動小数点数型の値や、その他多くの値に関する計算が難しく、構文もまた通常の関数とはかけ離れていた(浮動小数点数型の値の計算は、分数形式にすれば、できることはできる)。値をコンパイル時に計算するためには、今後はテンプレートメタプログラミングよりも<code>constexpr</code>を積極的に使用していくとよいだろう。</p>
<h2><a href="#relative-page" id="relative-page">関連項目</a></h2>
<ul>
<li><a href="user_defined_literals.html">C++11 ユーザー定義リテラル</a></li>
<li><a href="../cpp14/relaxing_constraints_on_constexpr.html">C++14 <code>constexpr</code>関数内での条件分岐とループの文を許可</a></li>
<li><a href="../cpp17/constexpr_lambda.html">C++17 <code>constexpr</code>ラムダ</a></li>
<li><a href="../cpp20/immediate_functions.html">C++20 常に定数式評価する<code>consteval</code></a></li>
<li><a href="../cpp20/allow_virtual_function_calls_in_constant_expressions.html">C++20 定数式からの仮想関数の呼び出しを許可</a></li>
<li><a href="../cpp20/allowing_dynamic_cast_polymorphic_typeid_in_constant_expressions.html">C++20 定数式での<code>dynamic_cast</code>、多態的な<code>typeid</code>を許可</a></li>
<li><a href="../cpp20/try-catch_blocks_in_constexpr_functions.html">C++20 <code>constexpr</code>関数内でのtry-catchブロックを許可</a></li>
<li><a href="../cpp20/changing_the_active_member_of_a_union_inside_constexpr.html">C++20 定数式内での共用体のアクティブメンバの変更を許可</a></li>
<li><a href="../cpp20/permitting_trivial_default_initialization_in_constexpr_contexts.html">C++20 <code>constexpr</code>関数内でのトリビアルなデフォルト初期化を許可</a></li>
<li><a href="../cpp20/enabling_constexpr_intrinsics_by_permitting_unevaluated_inline-assembly_in_constexpr_functions.html">C++20 <code>constexpr</code>関数内で未評価のインラインアセンブリを許可することによる組み込み関数の<code>constexpr</code>有効化</a></li>
<li><a href="../cpp20/constinit.html">C++20 コンパイル時初期化を強制する<code>constinit</code>キーワードを追加</a></li>
<li><a href="../cpp20/more_constexpr_containers.html">C++20 可変サイズをもつコンテナの<code>constexpr</code>化</a></li>
<li><a href="../cpp23/relaxing_some_constexpr_restrictions.html">C++23 <code>constexpr</code>関数が定数実行できない場合でも適格とする</a></li>
<li><a href="../cpp23/permitting_static_constexpr_variables_in_constexpr_functions.html">C++23 <code>constexpr</code>関数内での<code>static constexpr</code>変数を許可</a></li>
<li><a href="../cpp23/consteval_needs_to_propagate_up.html">C++23 <code>constexpr</code>関数内で<code>consteval</code>関数を呼び出せない問題を軽減</a></li>
<li><a href="../cpp26/allowing_exception_throwing_in_constant-evaluation.html">C++26 定数評価での例外送出を許可</a></li>
<li><a href="../cpp26/constexpr_cast_from_voidptr.html">C++26 定数式での<code>void*</code>からポインタ型へのキャストを許可</a></li>
<li><a href="../cpp26/constexpr_placement_new.html">C++26 <code>constexpr</code>配置<code>new</code></a></li>
<li><a href="../cpp26/constexpr_structured_bindings_and_references_to_constexpr_variables.html">C++26 <code>constexpr</code>構造化束縛の許可と、<code>constexpr</code>参照の制限緩和</a></li>
</ul>
<h2>参照</h2>
<ul>
<li><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1521.pdf" target="_blank">N1521 Generalized Constant Expressions</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1972.pdf" target="_blank">N1972 Generalized Constant Expressions — Revision 2</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1980.pdf" target="_blank">N1980 Generalized Constant Expressions — Revision 3</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2116.pdf" target="_blank">N2116 Generalized Constant Expressions — Revision 4</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf" target="_blank">N2235 Generalized Constant Expressions — Revision 5</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#644" target="_blank">CWG Issue 644. Should a trivial class type be a literal type?</a><ul>
<li>リテラル型のメンバ変数のみを持つクラスは、<code>constexpr</code>コンストラクタを明示的に定義しなくても、リテラル型となる</li>
</ul>
</li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#699" target="_blank">CWG Issue 699. Must constexpr member functions be defined in the class member-specification?</a><ul>
<li>ゼロ割りの扱い、再帰回数の規定</li>
</ul>
</li>
</ul></div>
</div>
</div>
</div>
<div id="sidebar" class="col-sm-3 col-sm-pull-9">
</div>
</div>
</div>
</main>
<footer class="footer navbar navbar-default">
<div class="container-fluid">
<p><small>
本サイトの情報は、
<a href="https://creativecommons.org/licenses/by/4.0/deed.ja" rel="nofollow">クリエイティブ・コモンズ 表示 4.0 非移植 ライセンス(CC BY)</a>
の下に提供されています。
</small></p>
</div>
</footer>
</body>
</html>