-
Notifications
You must be signed in to change notification settings - Fork 769
/
Copy pathdeclarations.tex
9613 lines (8765 loc) · 321 KB
/
declarations.tex
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
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%!TEX root = std.tex
\rSec0[dcl.dcl]{Declarations}%
\indextext{declaration|(}
\gramSec[gram.dcl]{Declarations}
\indextext{linkage specification|see{specification, linkage}}
\rSec1[dcl.pre]{Preamble}
\pnum
Declarations generally specify how names are to be interpreted. Declarations have
the form
\begin{bnf}
\nontermdef{declaration-seq}\br
declaration\br
declaration-seq declaration
\end{bnf}
\begin{bnf}
\nontermdef{declaration}\br
name-declaration\br
special-declaration
\end{bnf}
\begin{bnf}
\nontermdef{name-declaration}\br
block-declaration\br
nodeclspec-function-declaration\br
function-definition\br
friend-type-declaration\br
template-declaration\br
deduction-guide\br
linkage-specification\br
namespace-definition\br
empty-declaration\br
attribute-declaration\br
module-import-declaration
\end{bnf}
\begin{bnf}
\nontermdef{special-declaration}\br
explicit-instantiation\br
explicit-specialization\br
export-declaration
\end{bnf}
\begin{bnf}
\nontermdef{block-declaration}\br
simple-declaration\br
asm-declaration\br
namespace-alias-definition\br
using-declaration\br
using-enum-declaration\br
using-directive\br
static_assert-declaration\br
alias-declaration\br
opaque-enum-declaration
\end{bnf}
\begin{bnf}
\nontermdef{nodeclspec-function-declaration}\br
\opt{attribute-specifier-seq} declarator \terminal{;}
\end{bnf}
\begin{bnf}
\nontermdef{alias-declaration}\br
\keyword{using} identifier \opt{attribute-specifier-seq} \terminal{=} defining-type-id \terminal{;}
\end{bnf}
\begin{bnf}
\nontermdef{attributed-identifier}\br
identifier \opt{attribute-specifier-seq}
\end{bnf}
\begin{bnf}
\nontermdef{attributed-identifier-list}\br
attributed-identifier\br
attributed-identifier-list \terminal{,} attributed-identifier
\end{bnf}
\begin{bnf}
\nontermdef{structured-binding-declaration}\br
\opt{attribute-specifier-seq} decl-specifier-seq \opt{ref-qualifier} \terminal{[} attributed-identifier-list \terminal{]}
\end{bnf}
\begin{bnf}
\nontermdef{simple-declaration}\br
decl-specifier-seq \opt{init-declarator-list} \terminal{;}\br
attribute-specifier-seq decl-specifier-seq init-declarator-list \terminal{;}\br
structured-binding-declaration initializer \terminal{;}
\end{bnf}
\begin{bnf}
\nontermdef{static_assert-message}\br
unevaluated-string\br
constant-expression
\end{bnf}
\begin{bnf}
\nontermdef{static_assert-declaration}\br
\keyword{static_assert} \terminal{(} constant-expression \terminal{)} \terminal{;}\br
\keyword{static_assert} \terminal{(} constant-expression \terminal{,} static_assert-message \terminal{)} \terminal{;}
\end{bnf}
\begin{bnf}
\nontermdef{empty-declaration}\br
\terminal{;}
\end{bnf}
\begin{bnf}
\nontermdef{attribute-declaration}\br
attribute-specifier-seq \terminal{;}
\end{bnf}
\begin{note}
\grammarterm{asm-declaration}{s} are described in~\ref{dcl.asm}, and
\grammarterm{linkage-specification}{s} are described in~\ref{dcl.link};
\grammarterm{function-definition}{s} are described in~\ref{dcl.fct.def} and
\grammarterm{template-declaration}{s} and
\grammarterm{deduction-guide}{s} are described in \ref{temp.deduct.guide};
\grammarterm{namespace-definition}{s} are described in~\ref{namespace.def},
\grammarterm{using-declaration}{s} are described in~\ref{namespace.udecl} and
\grammarterm{using-directive}{s} are described in~\ref{namespace.udir}.
\end{note}
\pnum
\indextext{declaration}%
\indextext{scope}%
Certain declarations contain one or more scopes\iref{basic.scope.scope}.
Unless otherwise stated, utterances in
\ref{dcl.dcl} about components in, of, or contained by a
declaration or subcomponent thereof refer only to those components of
the declaration that are \emph{not} nested within scopes nested within
the declaration.
\pnum
If a \grammarterm{name-declaration} matches
the syntactic requirements of \grammarterm{friend-type-declaration},
it is a \grammarterm{friend-type-declaration}.
\pnum
A
\grammarterm{simple-declaration} or
\grammarterm{nodeclspec-function-declaration} of the form
\begin{ncsimplebnf}
\opt{attribute-specifier-seq} \opt{decl-specifier-seq} \opt{init-declarator-list} \terminal{;}
\end{ncsimplebnf}
is divided into three parts.
Attributes are described in~\ref{dcl.attr}.
\grammarterm{decl-specifier}{s}, the principal components of
a \grammarterm{decl-specifier-seq}, are described in~\ref{dcl.spec}.
\grammarterm{declarator}{s}, the components of an
\grammarterm{init-declarator-list}, are described in \ref{dcl.decl}.
The \grammarterm{attribute-specifier-seq}
appertains to each of the entities declared by
the \grammarterm{declarator}{s}
of the \grammarterm{init-declarator-list}.
\begin{note}
In the declaration for an entity, attributes appertaining to that
entity can appear at the start of the declaration and after the
\grammarterm{declarator-id} for that declaration.
\end{note}
\begin{example}
\begin{codeblock}
[[noreturn]] void f [[noreturn]] (); // OK
\end{codeblock}
\end{example}
\pnum
If a \grammarterm{declarator-id} is a name, the
\grammarterm{init-declarator} and (hence) the declaration introduce that name.
\begin{note}
Otherwise, the \grammarterm{declarator-id} is
a \grammarterm{qualified-id} or
names a destructor or
its \grammarterm{unqualified-id} is a \grammarterm{template-id} and
no name is introduced.
\end{note}
The \grammarterm{defining-type-specifier}{s}\iref{dcl.type} in
the \grammarterm{decl-specifier-seq} and
the recursive \grammarterm{declarator} structure
describe a type\iref{dcl.meaning},
which is then associated with the \grammarterm{declarator-id}.
\pnum
\indextext{identifier}%
\indextext{declarator}%
In a \grammarterm{simple-declaration}, the optional
\grammarterm{init-declarator-list} can be omitted only when declaring a
class\iref{class.pre} or enumeration\iref{dcl.enum}, that is,
when the \grammarterm{decl-specifier-seq} contains either a
\grammarterm{class-specifier}, an \grammarterm{elaborated-type-specifier} with
a \grammarterm{class-key}\iref{class.name}, or an
\grammarterm{enum-specifier}. In these cases and whenever a
\grammarterm{class-specifier} or \grammarterm{enum-specifier} is present in
the \grammarterm{decl-specifier-seq}, the identifiers in these specifiers
are also declared (as
\grammarterm{class-name}{s}, \grammarterm{enum-name}{s}, or
\grammarterm{enumerator}{s}, depending on the syntax). In such cases,
the \grammarterm{decl-specifier-seq} shall (re)introduce one or more names into
the program.
\begin{example}
\begin{codeblock}
enum { }; // error
typedef class { }; // error
\end{codeblock}
\end{example}
\pnum
A \grammarterm{simple-declaration} or a \grammarterm{condition}
with a \grammarterm{structured-binding-declaration} is called
a \defn{structured binding declaration}\iref{dcl.struct.bind}.
Each \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq}
shall be
\tcode{static},
\tcode{thread_local},
\tcode{auto}\iref{dcl.spec.auto}, or
a \grammarterm{cv-qualifier}.
\begin{example}
\begin{codeblock}
template<class T> concept C = true;
C auto [x, y] = std::pair{1, 2}; // error: constrained \grammarterm{placeholder-type-specifier}
// not permitted for structured bindings
\end{codeblock}
\end{example}
The \grammarterm{initializer} shall be
of the form ``\tcode{=} \grammarterm{assignment-expression}'',
of the form ``\tcode{\{} \grammarterm{assignment-expression} \tcode{\}}'',
or
of the form ``\tcode{(} \grammarterm{assignment-expression} \tcode{)}''.
If the \grammarterm{structured-binding-declaration} appears as
a \grammarterm{condition},
the \grammarterm{assignment-expression} shall be of non-union class type.
Otherwise,
the \grammarterm{assignment-expression} shall be of
array or non-union class type.
\pnum
If the \grammarterm{decl-specifier-seq} contains the \keyword{typedef}
specifier, the declaration is a \defnx{typedef declaration}{declaration!typedef}
and each \grammarterm{declarator-id}
is declared to be a \grammarterm{typedef-name}, synonymous with its
associated type\iref{dcl.typedef}.
\begin{note}
Such a \grammarterm{declarator-id} is
an \grammarterm{identifier}\iref{class.conv.fct}.
\end{note}
Otherwise, if the type associated with a \grammarterm{declarator-id}
is a function type\iref{dcl.fct},
the declaration is a \defnx{function declaration}{declaration!function}.
Otherwise, if the type associated with a \grammarterm{declarator-id}
is an object or reference type, the declaration is
an \defnx{object declaration}{declaration!object}.
Otherwise, the program is ill-formed.
\begin{example}
\begin{codeblock}
int f(), x; // OK, function declaration for \tcode{f} and object declaration for \tcode{x}
extern void g(), // OK, function declaration for \tcode{g}
y; // error: \tcode{void} is not an object type
\end{codeblock}
\end{example}
\pnum
\indextext{initialization!definition and}%
An object definition causes
storage of appropriate size and alignment to be reserved and
any appropriate initialization\iref{dcl.init} to be done.
\pnum
\indextext{definition!declaration as}%
Syntactic components beyond those found in the general form of
\grammarterm{simple-declaration} are added to a function declaration to make a
\grammarterm{function-definition}.
A token sequence starting with \tcode{\{} or \tcode{=}
is treated as a \grammarterm{function-body}\iref{dcl.fct.def.general}
if the type of the \grammarterm{declarator-id}\iref{dcl.meaning.general}
is a function type, and
is otherwise
treated as a \grammarterm{brace-or-equal-initializer}\iref{dcl.init.general}.
\begin{note}
If the declaration acquires a function type through template instantiation,
the program is ill-formed; see \ref{temp.spec.general}.
The function type of a function definition
cannot be specified with a \grammarterm{typedef-name}\iref{dcl.fct}.
\end{note}
\pnum
A \grammarterm{nodeclspec-function-declaration} shall declare a
constructor, destructor, or conversion function.
\begin{note}
Because a member function cannot be subject to a non-defining declaration
outside of a class definition\iref{class.mfct}, a \grammarterm{nodeclspec-function-declaration}
can only be used in a \grammarterm{template-declaration}\iref{temp.pre},
\grammarterm{explicit-instantiation}\iref{temp.explicit}, or
\grammarterm{explicit-specialization}\iref{temp.expl.spec}.
\end{note}
\pnum
If a \grammarterm{static_assert-message}
matches the syntactic requirements of \grammarterm{unevaluated-string},
it is an \grammarterm{unevaluated-string} and
the text of the \grammarterm{static_assert-message} is
the text of the \grammarterm{unevaluated-string}.
Otherwise, a \grammarterm{static_assert-message} shall be an expression $M$
such that
\begin{itemize}
\item
the expression \tcode{$M$.size()} is
implicitly convertible to the type \tcode{std::size_t}, and
\item
the expression \tcode{$M$.data()} is
implicitly convertible to the type ``pointer to \tcode{\keyword{const} \keyword{char}}''.
\end{itemize}
\pnum
\indextext{\idxcode{static_assert}}%
In a \grammarterm{static_assert-declaration},
the \grammarterm{constant-expression} $E$
is contextually converted to \keyword{bool} and
the converted expression shall be a constant expression\iref{expr.const}.
If the value of the expression $E$ when so converted is \tcode{true} or
the expression is evaluated in the context of a template definition,
the declaration has no effect and
the \grammarterm{static_assert-message} is
an unevaluated operand\iref{term.unevaluated.operand}.
Otherwise,
the \grammarterm{static_assert-declaration} \defnx{fails}{\idxcode{static_assert}!failed} and
\begin{itemize}
\item
the program is ill-formed, and
\item
if the \grammarterm{static_assert-message} is
a \grammarterm{constant-expression} $M$,
\begin{itemize}
\item
\tcode{$M$.size()} shall be a converted constant expression of
type \tcode{std::size_t} and
let $N$ denote the value of that expression,
\item
\tcode{$M$.data()}, implicitly converted to
the type ``pointer to \tcode{\keyword{const} \keyword{char}}'',
shall be a core constant expression and let $D$ denote the converted expression,
\item
for each $i$ where $0 \le i < N$,
\tcode{$D$[$i$]} shall be an integral constant expression, and
\item
the text of the \grammarterm{static_assert-message} is formed by
the sequence of $N$ code units, starting at $D$, of
the ordinary literal encoding\iref{lex.charset}.
\end{itemize}
\end{itemize}
\pnum
\recommended
When a \grammarterm{static_assert-declaration} fails,
the resulting diagnostic message should include the text of
the \grammarterm{static_assert-message}, if one is supplied.
\begin{example}
\begin{codeblock}
static_assert(sizeof(int) == sizeof(void*), "wrong pointer size");
static_assert(sizeof(int[2])); // OK, narrowing allowed
template <class T>
void f(T t) {
if constexpr (sizeof(T) == sizeof(int)) {
use(t);
} else {
static_assert(false, "must be int-sized");
}
}
void g(char c) {
f(0); // OK
f(c); // error on implementations where \tcode{sizeof(int) > 1}: must be \tcode{int}-sized
}
\end{codeblock}
\end{example}
\pnum
An \grammarterm{empty-declaration} has no effect.
\pnum
Except where otherwise specified, the meaning of an \grammarterm{attribute-declaration}
is \impldef{meaning of attribute declaration}.
\rSec1[dcl.spec]{Specifiers}%
\rSec2[dcl.spec.general]{General}%
\indextext{specifier|(}
\pnum
\indextext{specifier!declaration}%
The specifiers that can be used in a declaration are
\begin{bnf}
\nontermdef{decl-specifier}\br
storage-class-specifier\br
defining-type-specifier\br
function-specifier\br
\keyword{friend}\br
\keyword{typedef}\br
\keyword{constexpr}\br
\keyword{consteval}\br
\keyword{constinit}\br
\keyword{inline}
\end{bnf}
\begin{bnf}
\nontermdef{decl-specifier-seq}\br
decl-specifier \opt{attribute-specifier-seq}\br
decl-specifier decl-specifier-seq
\end{bnf}
The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{decl-specifier-seq}
appertains to the type determined by the preceding
\grammarterm{decl-specifier}{s}\iref{dcl.meaning}. The \grammarterm{attribute-specifier-seq}
affects the type only for the declaration it appears in, not other declarations involving the
same type.
\pnum
At most one of each of the \grammarterm{decl-specifier}s
\keyword{friend}, \keyword{typedef}, or \keyword{inline}
shall appear in a \grammarterm{decl-specifier-seq}.
At most one of
the \keyword{constexpr}, \keyword{consteval}, and \keyword{constinit} keywords
shall appear in a \grammarterm{decl-specifier-seq}.
\pnum
\indextext{ambiguity!declaration type}%
If a \grammarterm{type-name} is encountered while parsing a \grammarterm{decl-specifier-seq},
it is interpreted as part of the \grammarterm{decl-specifier-seq} if and only if there is no
previous \grammarterm{defining-type-specifier} other than a \grammarterm{cv-qualifier} in the
\grammarterm{decl-specifier-seq}.
The sequence shall be self-consistent as
described below.
\begin{example}
\begin{codeblock}
typedef char* Pc;
static Pc; // error: name missing
\end{codeblock}
Here, the declaration \keyword{static} \tcode{Pc} is ill-formed because no
name was specified for the static variable of type \tcode{Pc}. To get a
variable called \tcode{Pc}, a \grammarterm{type-specifier} (other than
\keyword{const} or \tcode{volatile}) has to be present to indicate that
the \grammarterm{typedef-name} \tcode{Pc} is the name being (re)declared,
rather than being part of the \grammarterm{decl-specifier} sequence. For
another example,
\begin{codeblock}
void f(const Pc); // \tcode{void f(char* const)} (not \tcode{const char*})
void g(const int Pc); // \tcode{void g(const int)}
\end{codeblock}
\end{example}
\pnum
\indextext{\idxcode{signed}!typedef@\tcode{typedef} and}%
\indextext{\idxcode{unsigned}!typedef@\tcode{typedef} and}%
\indextext{\idxcode{long}!typedef@\tcode{typedef} and}%
\indextext{\idxcode{short}!typedef@\tcode{typedef} and}%
\begin{note}
Since \tcode{signed}, \tcode{unsigned}, \tcode{long}, and \tcode{short}
by default imply \tcode{int}, a \grammarterm{type-name} appearing after one
of those specifiers is treated as the name being (re)declared.
\begin{example}
\begin{codeblock}
void h(unsigned Pc); // \tcode{void h(unsigned int)}
void k(unsigned int Pc); // \tcode{void k(unsigned int)}
\end{codeblock}
\end{example}
\end{note}
\rSec2[dcl.stc]{Storage class specifiers}%
\indextext{specifier!storage class}%
\indextext{declaration!storage class}%
\indextext{\idxcode{static}}%
\indextext{\idxcode{thread_local}}%
\indextext{\idxcode{extern}}%
\indextext{\idxcode{mutable}}
\pnum
The storage class specifiers are
\begin{bnf}
\nontermdef{storage-class-specifier}\br
\keyword{static}\br
\keyword{thread_local}\br
\keyword{extern}\br
\keyword{mutable}
\end{bnf}
At most one \grammarterm{storage-class-specifier} shall appear in a given
\grammarterm{decl-specifier-seq}, except that \keyword{thread_local} may appear with \keyword{static} or
\keyword{extern}. If \keyword{thread_local} appears in any declaration of
a variable it shall be present in all declarations of that entity. If a
\grammarterm{storage-class-specifier}
appears in a \grammarterm{decl-specifier-seq}, there can be no
\tcode{typedef} specifier in the same \grammarterm{decl-specifier-seq} and
the \grammarterm{init-declarator-list} or \grammarterm{member-declarator-list}
of the declaration shall not be
empty (except for an anonymous union declared in a namespace scope\iref{class.union.anon}). The
\grammarterm{storage-class-specifier} applies to the name declared by each
\grammarterm{init-declarator} in the list and not to any names declared by
other specifiers.
\begin{note}
See \ref{temp.expl.spec} and \ref{temp.explicit} for restrictions
in explicit specializations and explicit instantiations, respectively.
\end{note}
\pnum
\begin{note}
A variable declared without a \grammarterm{storage-class-specifier}
at block scope or declared as a function parameter
has automatic storage duration by default\iref{basic.stc.auto}.
\end{note}
\pnum
The \keyword{thread_local} specifier
indicates that the named entity has thread storage duration\iref{basic.stc.thread}. It
shall be applied only
to the declaration of a variable of namespace or block scope,
to a structured binding declaration\iref{dcl.struct.bind}, or
to the declaration of a static data member.
When \keyword{thread_local} is applied to a variable of block scope the
\grammarterm{storage-class-specifier} \keyword{static} is implied if no other
\grammarterm{storage-class-specifier} appears in the
\grammarterm{decl-specifier-seq}.
\pnum
\indextext{restriction!\idxcode{static}}%
The \keyword{static} specifier shall be applied only
to the declaration of a variable or function,
to a structured binding declaration\iref{dcl.struct.bind}, or
to the declaration of an anonymous union\iref{class.union.anon}.
There can be no
\keyword{static} function declarations within a block, nor any
\keyword{static} function parameters. A \tcode{static} specifier used in
the declaration of a variable declares the variable to have static storage
duration\iref{basic.stc.static}, unless accompanied by the
\keyword{thread_local} specifier, which declares the variable to have thread
storage duration\iref{basic.stc.thread}. A \keyword{static} specifier can be
used in declarations of class members;~\ref{class.static} describes its
effect.
\indextext{\idxcode{static}!linkage of}%
For the linkage of a name declared with a \keyword{static} specifier,
see~\ref{basic.link}.
\pnum
\indextext{restriction!\idxcode{extern}}%
The \keyword{extern} specifier shall be applied only to the declaration of a variable
or function. The \keyword{extern} specifier shall not be used in the
declaration of a class member or function parameter.
\indextext{\idxcode{extern}!linkage of}%
\indextext{consistency!linkage}%
For the linkage of a name declared with an \keyword{extern} specifier,
see~\ref{basic.link}.
\begin{note}
The \keyword{extern} keyword can also be used in
\grammarterm{explicit-instantiation}{s} and
\grammarterm{linkage-specification}{s}, but it is not a
\grammarterm{storage-class-specifier} in such contexts.
\end{note}
\pnum
All declarations for a given entity shall give its name the same linkage.
\begin{note}
The linkage given by some declarations is affected by previous declarations.
Overloads are distinct entities.
\end{note}
\begin{example}
\begin{codeblock}
static char* f(); // \tcode{f()} has internal linkage
char* f() // \tcode{f()} still has internal linkage
{ @\commentellip@ }
char* g(); // \tcode{g()} has external linkage
static char* g() // error: inconsistent linkage
{ @\commentellip@ }
void h();
inline void h(); // external linkage
inline void l();
void l(); // external linkage
inline void m();
extern void m(); // external linkage
static void n();
inline void n(); // internal linkage
static int a; // \tcode{a} has internal linkage
int a; // error: two definitions
static int b; // \tcode{b} has internal linkage
extern int b; // \tcode{b} still has internal linkage
int c; // \tcode{c} has external linkage
static int c; // error: inconsistent linkage
extern int d; // \tcode{d} has external linkage
static int d; // error: inconsistent linkage
\end{codeblock}
\end{example}
\pnum
\indextext{declaration!forward}%
The name of a declared but undefined class can be used in an
\keyword{extern} declaration. Such a declaration can only be used in ways
that do not require a complete class type.
\begin{example}
\begin{codeblock}
struct S;
extern S a;
extern S f();
extern void g(S);
void h() {
g(a); // error: \tcode{S} is incomplete
f(); // error: \tcode{S} is incomplete
}
\end{codeblock}
\end{example}
\pnum
The \keyword{mutable} specifier shall appear only in the declaration of
a non-static data member\iref{class.mem}
whose type is neither const-qualified nor a reference type.
\begin{example}
\begin{codeblock}
class X {
mutable const int* p; // OK
mutable int* const q; // error
};
\end{codeblock}
\end{example}
\pnum
\begin{note}
The \keyword{mutable} specifier on a class data member nullifies a
\keyword{const} specifier applied to the containing class object and
permits modification of the mutable class member even though the rest of
the object is const\iref{basic.type.qualifier,dcl.type.cv}.
\end{note}
\rSec2[dcl.fct.spec]{Function specifiers}%
\indextext{specifier!function}%
\indextext{function|seealso{friend function}}
\indextext{function|seealso{member function}}
\indextext{function|seealso{inline function}}
\indextext{function|seealso{virtual function}}
\pnum
A
\grammarterm{function-specifier}
can be used only in a function declaration.
At most one \grammarterm{explicit-specifier} and
at most one \keyword{virtual} keyword shall appear in
a \grammarterm{decl-specifier-seq}.
\begin{bnf}
\nontermdef{function-specifier}\br
\keyword{virtual}\br
explicit-specifier
\end{bnf}
\begin{bnf}
\nontermdef{explicit-specifier}\br
\keyword{explicit} \terminal{(} constant-expression \terminal{)}\br
\keyword{explicit}
\end{bnf}
\pnum
\indextext{specifier!\idxcode{virtual}}%
The \keyword{virtual} specifier shall be used only in the initial
declaration of a non-static member function; see~\ref{class.virtual}.
\pnum
\indextext{specifier!\idxcode{explicit}}%
An \grammarterm{explicit-specifier} shall be used only in the declaration of
a constructor or conversion function within its class definition;
see~\ref{class.conv.ctor} and~\ref{class.conv.fct}.
\pnum
In an \grammarterm{explicit-specifier},
the \grammarterm{constant-expression}, if supplied, shall be a
contextually converted constant expression of type \tcode{bool}\iref{expr.const}.
The \grammarterm{explicit-specifier} \keyword{explicit}
without a \grammarterm{constant-expression} is equivalent to
the \grammarterm{explicit-specifier} \tcode{explicit(true)}.
If the constant expression evaluates to \tcode{true},
the function is explicit. Otherwise, the function is not explicit.
A \tcode{(} token that follows \keyword{explicit} is parsed as
part of the \grammarterm{explicit-specifier}.
\begin{example}
\begin{codeblock}
struct S {
explicit(sizeof(char[2])) S(char); // error: narrowing conversion of value 2 to type \keyword{bool}
explicit(sizeof(char)) S(bool); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing
};
\end{codeblock}
\end{example}
\rSec2[dcl.typedef]{The \keyword{typedef} specifier}%
\indextext{specifier!\idxcode{typedef}}
\pnum
Declarations containing the \grammarterm{decl-specifier} \keyword{typedef}
declare identifiers that can be used later for naming
fundamental\iref{basic.fundamental} or compound\iref{basic.compound}
types. The \keyword{typedef} specifier shall not be
combined in a \grammarterm{decl-specifier-seq} with any other kind of
specifier except a \grammarterm{defining-type-specifier}, and it shall not be used in the
\grammarterm{decl-specifier-seq} of a
\grammarterm{parameter-declaration}\iref{dcl.fct} nor in the
\grammarterm{decl-specifier-seq} of a
\grammarterm{function-definition}\iref{dcl.fct.def}.
If a \keyword{typedef} specifier appears in a declaration without a \grammarterm{declarator},
the program is ill-formed.
\begin{bnf}
\nontermdef{typedef-name}\br
identifier\br
simple-template-id
\end{bnf}
A name declared with the \keyword{typedef} specifier becomes a
\grammarterm{typedef-name}.
A \grammarterm{typedef-name} names
the type associated with the \grammarterm{identifier}\iref{dcl.decl}
or \grammarterm{simple-template-id}\iref{temp.pre};
\indextext{declaration!typedef@\tcode{typedef} as type}%
\indextext{equivalence!type}%
\indextext{synonym!type name as}%
a \grammarterm{typedef-name} is thus a synonym for another type. A
\grammarterm{typedef-name} does not introduce a new type the way a class
declaration\iref{class.name} or enum declaration\iref{dcl.enum} does.
\begin{example}
After
\begin{codeblock}
typedef int MILES, *KLICKSP;
\end{codeblock}
the constructions
\begin{codeblock}
MILES distance;
extern KLICKSP metricp;
\end{codeblock}
are all correct declarations; the type of \tcode{distance} is
\tcode{int} and that of \tcode{metricp} is ``pointer to \tcode{int}''.
\end{example}
\pnum
A \grammarterm{typedef-name} can also be introduced by an
\grammarterm{alias-declaration}. The \grammarterm{identifier} following the
\tcode{using} keyword is not looked up; it becomes a \grammarterm{typedef-name}
and the optional \grammarterm{attribute-specifier-seq} following the
\grammarterm{identifier} appertains to that \grammarterm{typedef-name}.
Such a \grammarterm{typedef-name} has the same
semantics as if it were introduced by the \keyword{typedef} specifier. In
particular, it does not define a new type.
\begin{example}
\begin{codeblock}
using handler_t = void (*)(int);
extern handler_t ignore;
extern void (*ignore)(int); // redeclare \tcode{ignore}
template<class T> struct P { };
using cell = P<cell*>; // error: \tcode{cell} not found\iref{basic.scope.pdecl}
\end{codeblock}
\end{example}
The \grammarterm{defining-type-specifier-seq}
of the \grammarterm{defining-type-id} shall not define
a class or enumeration if the \grammarterm{alias-declaration}
is the \grammarterm{declaration} of a \grammarterm{template-declaration}.
\pnum
\indextext{class name!\idxcode{typedef}}%
A \grammarterm{simple-template-id} is only a \grammarterm{typedef-name}
if its \grammarterm{template-name} names
an alias template or a template \grammarterm{template-parameter}.
\begin{note}
A \grammarterm{simple-template-id} that names a class template specialization
is a \grammarterm{class-name}\iref{class.name}.
If a \grammarterm{typedef-name} is used to identify the subject of an
\grammarterm{elaborated-type-specifier}\iref{dcl.type.elab}, a class
definition\iref{class}, a constructor
declaration\iref{class.ctor}, or a destructor
declaration\iref{class.dtor}, the program is ill-formed.
\end{note}
\begin{example}
\begin{codeblock}
struct S {
S();
~S();
};
typedef struct S T;
S a = T(); // OK
struct T * p; // error
\end{codeblock}
\end{example}
\pnum
\indextext{class name!\idxcode{typedef}}%
\indextext{enum name!\idxcode{typedef}}%
\indextext{class!unnamed}%
An unnamed class or enumeration $C$ defined in a typedef declaration has
the first \grammarterm{typedef-name}
declared by the declaration to be of type $C$
as its \defn{typedef name for linkage purposes}\iref{basic.link}.
\begin{note}
A typedef declaration involving a \grammarterm{lambda-expression}
does not itself define the associated closure type,
and so the closure type is not given a typedef name for linkage purposes.
\end{note}
\begin{example}
\begin{codeblock}
typedef struct { } *ps, S; // \tcode{S} is the typedef name for linkage purposes
typedef decltype([]{}) C; // the closure type has no typedef name for linkage purposes
\end{codeblock}
\end{example}
\pnum
An unnamed class with a typedef name for linkage purposes shall not
\begin{itemize}
\item
declare any members
other than non-static data members, member enumerations, or member classes,
\item
have any base classes or default member initializers, or
\item
contain a \grammarterm{lambda-expression},
\end{itemize}
and all member classes shall also satisfy these requirements (recursively).
\begin{example}
\begin{codeblock}
typedef struct {
int f() {}
} X; // error: struct with typedef name for linkage has member functions
\end{codeblock}
\end{example}
\rSec2[dcl.friend]{The \keyword{friend} specifier}%
\indextext{specifier!\idxcode{friend}}
\pnum
The \keyword{friend} specifier is used to specify access to class members;
see~\ref{class.friend}.
\rSec2[dcl.constexpr]{The \keyword{constexpr} and \keyword{consteval} specifiers}%
\indextext{specifier!\idxcode{constexpr}}
\indextext{specifier!\idxcode{consteval}}
\pnum
The \keyword{constexpr} specifier shall be applied only to
the definition of a variable or variable template or
the declaration of a function or function template.
The \keyword{consteval} specifier shall be applied only to
the declaration of a function or function template.
A function or static data member
declared with the \keyword{constexpr} or \keyword{consteval} specifier
on its first declaration
is implicitly an inline function or variable\iref{dcl.inline}.
If any declaration of a function or function template has
a \keyword{constexpr} or \keyword{consteval} specifier,
then all its declarations shall contain the same specifier.
\begin{note}
An explicit specialization can differ from the template declaration
with respect to the \keyword{constexpr} or \keyword{consteval} specifier.
\end{note}
\begin{note}
Function parameters cannot be declared \keyword{constexpr}.
\end{note}
\begin{example}
\begin{codeblock}
constexpr void square(int &x); // OK, declaration
constexpr int bufsz = 1024; // OK, definition
constexpr struct pixel { // error: \tcode{pixel} is a type
int x;
int y;
constexpr pixel(int); // OK, declaration
};
constexpr pixel::pixel(int a)
: x(a), y(x) // OK, definition
{ square(x); }
constexpr pixel small(2); // error: \tcode{square} not defined, so \tcode{small(2)}
// not constant\iref{expr.const} so \keyword{constexpr} not satisfied
constexpr void square(int &x) { // OK, definition
x *= x;
}
constexpr pixel large(4); // OK, \tcode{square} defined
int next(constexpr int x) { // error: not for parameters
return x + 1;
}
extern constexpr int memsz; // error: not a definition
\end{codeblock}
\end{example}
\pnum
A \keyword{constexpr} or \keyword{consteval} specifier
used in the declaration of a function
declares that function to be
a \defnx{constexpr function}{specifier!\idxcode{constexpr}!function}.
\begin{note}
A function or constructor declared with the \keyword{consteval} specifier
is an immediate function\iref{expr.const}.
\end{note}
A destructor, an allocation function, or a deallocation function
shall not be declared with the \keyword{consteval} specifier.
\pnum
\indextext{specifier!\idxcode{constexpr}!function}%
\indextext{constexpr function}%
A function is \defn{constexpr-suitable} if
\begin{itemize}
\item
it is not a coroutine\iref{dcl.fct.def.coroutine}, and
\item
if the function is a constructor or destructor,
its class does not have any virtual base classes.
\end{itemize}
Except for instantiated constexpr functions,
non-templated constexpr functions shall be constexpr-suitable.
\begin{example}
\begin{codeblock}
constexpr int square(int x)
{ return x * x; } // OK
constexpr long long_max()
{ return 2147483647; } // OK
constexpr int abs(int x) {
if (x < 0)
x = -x;
return x; // OK
}
constexpr int constant_non_42(int n) { // OK
if (n == 42) {
static int value = n;
return value;
}
return n;
}
constexpr int uninit() {
struct { int a; } s;
return s.a; // error: uninitialized read of \tcode{s.a}
}
constexpr int prev(int x)
{ return --x; } // OK
constexpr int g(int x, int n) { // OK
int r = 1;
while (--n > 0) r *= x;
return r;
}
\end{codeblock}
\end{example}
\pnum
An invocation of a constexpr function in a given context
produces the same result as
an invocation of an equivalent non-constexpr function in the same context
in all respects except that
\begin{itemize}
\item
an invocation of a constexpr function
can appear in a constant expression\iref{expr.const} and
\item
copy elision is not performed in a constant expression\iref{class.copy.elision}.
\end{itemize}
\begin{note}
Declaring a function constexpr can change whether an expression
is a constant expression.
This can indirectly cause calls to \tcode{std::is_constant_evaluated}
within an invocation of the function to produce a different value.
\end{note}
\begin{note}
It is possible to write a constexpr function for which
no invocation satisfies the requirements of a core constant expression.
\end{note}
\pnum
The \keyword{constexpr} and \keyword{consteval} specifiers have no
effect on the type of a constexpr function.
\begin{example}
\begin{codeblock}
constexpr int bar(int x, int y) // OK
{ return x + y + x*y; }
// ...
int bar(int x, int y) // error: redefinition of \tcode{bar}
{ return x * 2 + 3 * y; }
\end{codeblock}
\end{example}
\pnum
A \keyword{constexpr} specifier used in an object declaration
declares the object as const.
Such an object
shall have literal type and
shall be initialized.
In any \keyword{constexpr} variable declaration,
the full-expression of the initialization
shall be a constant expression\iref{expr.const}.