declaration-seq: declaration declaration-seq declaration
declaration: block-declaration nodeclspec-function-declaration function-definition template-declaration deduction-guide explicit-instantiation explicit-specialization linkage-specification namespace-definition empty-declaration attribute-declaration
block-declaration: simple-declaration asm-definition namespace-alias-definition using-declaration using-directive static_assert-declaration alias-declaration opaque-enum-declaration
nodeclspec-function-declaration: attribute-specifier-seq declarator ;
alias-declaration: using identifier attribute-specifier-seq = defining-type-id ;
simple-declaration: decl-specifier-seq init-declarator-list ; attribute-specifier-seq decl-specifier-seq init-declarator-list ; attribute-specifier-seq decl-specifier-seq ref-qualifier [ identifier-list ] initializer ;
static_assert-declaration: static_assert ( constant-expression ) ; static_assert ( constant-expression , string-literal ) ;
empty-declaration: ;
attribute-declaration: attribute-specifier-seq ;
attribute-specifier-seq decl-specifier-seq init-declarator-list ;
static_assert(char(-1) < 0, "this library requires plain 'char' to be signed");— end example
decl-specifier: storage-class-specifier defining-type-specifier function-specifier friend typedef constexpr inline
decl-specifier-seq: decl-specifier attribute-specifier-seq decl-specifier decl-specifier-seq
typedef char* Pc;
static Pc; // error: name missing
void f(const Pc); // void f(char* const) (not const char*) void g(const int Pc); // void g(const int)
storage-class-specifier: static thread_local extern mutable
static char* f(); // f() has internal linkage char* f() // f() still has internal linkage { /* ... */ } char* g(); // g() has external linkage static char* g() // error: inconsistent linkage { /* ... */ } 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; // a has internal linkage int a; // error: two definitions static int b; // b has internal linkage extern int b; // b still has internal linkage int c; // c has external linkage static int c; // error: inconsistent linkage extern int d; // d has external linkage static int d; // error: inconsistent linkage— end example
struct S;
extern S a;
extern S f();
extern void g(S);
void h() {
g(a); // error: S is incomplete
f(); // error: S is incomplete
} — end example
class X {
mutable const int* p; // OK
mutable int* const q; // ill-formed
}; — end examplefunction-specifier: virtual explicit
typedef-name: identifier
using handler_t = void (*)(int); extern handler_t ignore; extern void (*ignore)(int); // redeclare ignore using cell = pair<void*, cell*>; // ill-formed— end example
typedef struct s { /* ... */ } s;
typedef int I;
typedef int I;
typedef I I; — end example
struct S {
typedef struct A { } A; // OK
typedef struct B B; // OK
typedef A A; // error
}; — end example
struct S;
typedef struct S S;
int main() {
struct S* p; // OK
}
struct S { }; // OK
— end example
struct S {
S();
~S();
};
typedef struct S T;
S a = T(); // OK
struct T * p; // error
— end exampleconstexpr void square(int &x); // OK: declaration constexpr int bufsz = 1024; // OK: definition constexpr struct pixel { // error: 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: square not defined, so small(2) // not constant ([expr.const]) so constexpr not satisfied constexpr void square(int &x) { // OK: definition x *= x; } constexpr pixel large(4); // OK: square defined int next(constexpr int x) { // error: not for parameters return x + 1; } extern constexpr int memsz; // error: not a definition— end example
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 first(int n) {
static int value = n; // error: variable has static storage duration
return value;
}
constexpr int uninit() {
int a; // error: variable is uninitialized
return 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 example
struct Length {
constexpr explicit Length(int i = 0) : val(i) { }
private:
int val;
}; — end example
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
struct B {
constexpr B(int x) : i(0) { } // x is unused
int i;
};
int global;
struct D : B {
constexpr D() : B(global) { } // ill-formed, no diagnostic required
// lvalue-to-rvalue conversion on non-constant global
}; — end exampleconstexpr int bar(int x, int y) // OK { return x + y + x*y; } // ... int bar(int x, int y) // error: redefinition of bar { return x * 2 + 3 * y; }— end example
struct pixel {
int x, y;
};
constexpr pixel ur = { 1294, 1024 }; // OK
constexpr pixel origin; // error: initializer missing
— end exampletype-specifier: simple-type-specifier elaborated-type-specifier typename-specifier cv-qualifier
type-specifier-seq: type-specifier attribute-specifier-seq type-specifier type-specifier-seq
defining-type-specifier: type-specifier class-specifier enum-specifier
defining-type-specifier-seq: defining-type-specifier attribute-specifier-seq defining-type-specifier defining-type-specifier-seq
const int ci = 3; // cv-qualified (initialized as required) ci = 4; // ill-formed: attempt to modify const int i = 2; // not cv-qualified const int* cip; // pointer to const int cip = &i; // OK: cv-qualified access path to unqualified *cip = 4; // ill-formed: attempt to modify through ptr to const int* ip; ip = const_cast<int*>(cip); // cast needed to convert const int* to int* *ip = 4; // defined: *ip points to i, a non-const object const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object
struct X {
mutable int i;
int j;
};
struct Y {
X x;
Y();
};
const Y y;
y.x.i++; // well-formed: mutable member can be modified
y.x.j++; // ill-formed: const-qualified member modified
Y* p = const_cast<Y*>(&y); // cast away const-ness of y
p->x.i = 99; // well-formed: mutable member can be modified
p->x.j = 99; // undefined: modifies a const member
simple-type-specifier: nested-name-specifier type-name nested-name-specifier template simple-template-id nested-name-specifier template-name char char16_t char32_t wchar_t bool short int long signed unsigned float double void auto decltype-specifier
type-name: class-name enum-name typedef-name simple-template-id
decltype-specifier: decltype ( expression ) decltype ( auto )
Specifier(s) | Type |
type-name | the type named |
simple-template-id | the type as defined in [temp.names] |
template-name | placeholder for a type to be deduced |
char | “char” |
unsigned char | “unsigned char” |
signed char | “signed char” |
char16_t | “char16_t” |
char32_t | “char32_t” |
bool | “bool” |
unsigned | “unsigned int” |
unsigned int | “unsigned int” |
signed | “int” |
signed int | “int” |
int | “int” |
unsigned short int | “unsigned short int” |
unsigned short | “unsigned short int” |
unsigned long int | “unsigned long int” |
unsigned long | “unsigned long int” |
unsigned long long int | “unsigned long long int” |
unsigned long long | “unsigned long long int” |
signed long int | “long int” |
signed long | “long int” |
signed long long int | “long long int” |
signed long long | “long long int” |
long long int | “long long int” |
long long | “long long int” |
long int | “long int” |
long | “long int” |
signed short int | “short int” |
signed short | “short int” |
short int | “short int” |
short | “short int” |
wchar_t | “wchar_t” |
float | “float” |
double | “double” |
long double | “long double” |
void | “void” |
auto | placeholder for a type to be deduced |
decltype(auto) | placeholder for a type to be deduced |
decltype(expression) | the type as defined below |
const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 17; // type is const int&&
decltype(i) x2; // type is int
decltype(a->x) x3; // type is double
decltype((a->x)) x4 = x3; // type is const double&
— end example
template<class T> struct A { ~A() = delete; };
template<class T> auto h()
-> A<T>;
template<class T> auto i(T) // identity
-> T;
template<class T> auto f(T) // #1
-> decltype(i(h<T>())); // forces completion of A<T> and implicitly uses A<T>::~A()
// for the temporary introduced by the use of h().
// (A temporary is not introduced as a result of the use of i().)
template<class T> auto f(T) // #2
-> void;
auto g() -> void {
f(42); // OK: calls #2. (#1 is not a viable candidate: type deduction
// fails ([temp.deduct]) because A<int>::~A() is implicitly used in its
// decltype-specifier)
}
template<class T> auto q(T)
-> decltype((h<T>())); // does not force completion of A<T>; A<T>::~A() is not implicitly
// used within the context of this decltype-specifier
void r() {
q(42); // Error: deduction against q succeeds, so overload resolution selects
// the specialization “q(T) -> decltype((h<T>())) [with T=int]”.
// The return type is A<int>, so a temporary is introduced and its
// destructor is used, so the program is ill-formed.
} — end exampleelaborated-type-specifier: class-key attribute-specifier-seq nested-name-specifier identifier class-key simple-template-id class-key nested-name-specifier template simple-template-id enum nested-name-specifier identifier
class-key attribute-specifier-seq identifier ; friend class-key :: identifier ; friend class-key :: simple-template-id ; friend class-key nested-name-specifier identifier ; friend class-key nested-name-specifier template simple-template-id ;
friend class T;
( expression-list ) auto x = 5; // OK: x has type int const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int static auto y = 0.0; // OK: y has type double auto int r; // error: auto is not a storage-class-specifier auto f() -> int; // OK: f returns int auto g() { return 0.0; } // OK: g returns double auto h(); // OK: h's return type will be deduced when it is defined— end example
auto x = 5, *y = &x; // OK: auto is int auto a = 5, b = { 1, 2 }; // error: different types for auto— end example
auto f() { } // OK, return type is void
auto* g() { } // error, cannot deduce auto* from void()
— end exampleauto n = n; // error, n's type is unknown auto f(); void g() { &f; } // error, f's return type is unknown auto sum(int i) { if (i == 1) return i; // sum's return type is int else return sum(i-1)+i; // OK, sum's return type has been deduced }— end example
template <class T> auto f(T t) { return t; } // return type deduced at instantiation time
typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
template<class T> auto f(T* t) { return *t; }
void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,
// chooses second
— end example
auto f();
auto f() { return 42; } // return type is int
auto f(); // OK
int f(); // error, cannot be overloaded with auto f()
decltype(auto) f(); // error, auto and decltype(auto) don't match
template <typename T> auto g(T t) { return t; } // #1
template auto g(int); // OK, return type is int
template char g(char); // error, no matching template
template<> auto g(double); // OK, forward declaration with unknown return type
template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1
template char g(char); // OK, now there is a matching template
template auto g(float); // still matches #1
void h() { return g(42); } // error, ambiguous
template <typename T> struct A {
friend T frf(T);
};
auto frf(int i) { return i; } // not a friend of A<int>
— end example
template <typename T> auto f(T t) { return t; }
extern template auto f(int); // does not instantiate f<int>
int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
// instantiation definition is still required somewhere in the program
— end example
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int
— end exampleconst auto &i = expr;
template <class U> void f(const U& u);
int i; int&& f(); auto x2a(i); // decltype(x2a) is int decltype(auto) x2d(i); // decltype(x2d) is int auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)— end example
template<class T> struct container {
container(T t) {}
template<class Iter> container(Iter beg, Iter end);
};
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
std::vector<double> v = { /* ... */ };
container c(7); // OK, deduces int for T
auto d = container(v.begin(), v.end()); // OK, deduces double for T
container e{5, 6}; // error, int is not an iterator
— end exampleenum-name: identifier
enum-specifier: enum-head { enumerator-list } enum-head { enumerator-list , }
enum-head: enum-key attribute-specifier-seq enum-head-name enum-base
enum-head-name: nested-name-specifier identifier
opaque-enum-declaration: enum-key attribute-specifier-seq nested-name-specifier identifier enum-base ;
enum-key: enum enum class enum struct
enum-base: : type-specifier-seq
enumerator-list: enumerator-definition enumerator-list , enumerator-definition
enumerator-definition: enumerator enumerator = constant-expression
enumerator: identifier attribute-specifier-seq
struct S {
enum E : int {};
enum E : int {}; // error: redeclaration of enumeration
}; — end example
enum color { red, yellow, green=20, blue };
color col = red;
color* cp = &col;
if (*cp == blue) // ...
makes color a type describing various colors, and then declares
col as an object of that type, and cp as a pointer to an
object of that type.color c = 1; // error: type mismatch, no conversion from int to color int i = yellow; // OK: yellow converted to integral value 1, integral promotion
enum class Col { red, yellow, green };
int x = Col::red; // error: no Col to int conversion
Col y = Col::red;
if (y) { } // error: no Col to bool conversion
enum direction { left='l', right='r' };
void g() {
direction d; // OK
d = left; // OK
d = direction::right; // OK
}
enum class altitude { high='h', low='l' };
void h() {
altitude a; // OK
a = high; // error: high not in scope
a = altitude::low; // OK
} — end example
struct X {
enum direction { left='l', right='r' };
int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};
void g(X* p) {
direction d; // error: direction not in scope
int i;
i = p->f(left); // error: left not in scope
i = p->f(X::right); // OK
i = p->f(p->left); // OK
// ...
} — end examplenamespace-name: identifier namespace-alias
namespace-definition: named-namespace-definition unnamed-namespace-definition nested-namespace-definition
named-namespace-definition: inline namespace attribute-specifier-seq identifier { namespace-body }
unnamed-namespace-definition: inline namespace attribute-specifier-seq { namespace-body }
nested-namespace-definition: namespace enclosing-namespace-specifier :: identifier { namespace-body }
enclosing-namespace-specifier: identifier enclosing-namespace-specifier :: identifier
namespace-body: declaration-seq
namespace Outer {
int i;
namespace Inner {
void f() { i++; } // Outer::i
int i;
void g() { i++; } // Inner::i
}
} — end example
namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
} — end example
namespace E { namespace I { B } }
namespace A::B::C {
int i;
}
namespace A {
namespace B {
namespace C {
int i;
}
}
}inline namespace unique { /* empty body */ } using namespace unique ; namespace unique { namespace-body }
namespace { int i; } // unique::i
void f() { i++; } // unique::i++
namespace A {
namespace {
int i; // A::unique::i
int j; // A::unique::j
}
void g() { i++; } // A::unique::i++
}
using namespace A;
void h() {
i++; // error: unique::i or A::unique::i
A::i++; // A::unique::i
j++; // A::unique::j
} — end example
namespace X {
void f() { /* ... */ } // OK: introduces X::f()
namespace M {
void g(); // OK: introduces X::M::g()
}
using M::g;
void g(); // error: conflicts with X::M::g()
} — end example
namespace Q {
namespace V {
void f();
}
void V::f() { /* ... */ } // OK
void V::g() { /* ... */ } // error: g() is not yet a member of V
namespace V {
void g();
}
}
namespace R {
void Q::V::g() { /* ... */ } // error: R doesn't enclose Q
} — end example// Assume f and g have not yet been declared. void h(int); template <class T> void f2(T); namespace A { class X { friend void f(X); // A::f(X) is a friend class Y { friend void g(); // A::g is a friend friend void h(int); // A::h is a friend // ::h not considered friend void f2<>(int); // ::f2<>(int) is a friend }; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::g void f(X) { /* ... */ } // definition of A::f void h(int) { /* ... */ } // definition of A::h // A::f, A::g and A::h are visible here and known to be friends } using A::x; void h() { A::f(x); A::X::f(x); // error: f is not a member of A::X A::X::Y::g(); // error: g is not a member of A::X::Y }— end example
namespace-alias: identifier
namespace-alias-definition: namespace identifier = qualified-namespace-specifier ;
qualified-namespace-specifier: nested-name-specifier namespace-name
namespace Company_with_very_long_name { /* ... */ }
namespace CWVLN = Company_with_very_long_name;
namespace CWVLN = Company_with_very_long_name; // OK: duplicate
namespace CWVLN = CWVLN; — end exampleusing-declaration: using using-declarator-list ;
using-declarator-list: using-declarator ... using-declarator-list , using-declarator ...
using-declarator: typename nested-name-specifier unqualified-id
struct B {
void f(char);
void g(char);
enum E { e };
union { int x; };
};
struct D : B {
using B::f;
void f(int) { f('c'); } // calls B::f(char)
void g(int) { g('c'); } // recursively calls D::g(int)
}; — end example
template <typename... bases>
struct X : bases... {
using bases::g...;
};
X<B, D> x; // OK: B::g and D::g introduced
— end example
class C {
int g();
};
class D2 : public B {
using B::f; // OK: B is a base of D2
using B::e; // OK: e is an enumerator of base B
using B::x; // OK: x is a union member of base B
using C::g; // error: C isn't a base of D2
}; — end example
struct A {
template <class T> void f(T);
template <class T> struct X { };
};
struct B : A {
using A::f<double>; // ill-formed
using A::X<int>; // ill-formed
}; — end example
struct X {
int i;
static int s;
};
void f() {
using X::i; // error: X::i is a class member and this is not a member declaration.
using X::s; // error: X::s is a class member and this is not a member declaration.
} — end example
void f();
namespace A {
void g();
}
namespace X {
using ::f; // global f
using A::g; // A's g
}
void h()
{
X::f(); // calls ::f
X::g(); // calls A::g
} — end example
namespace A {
int i;
}
namespace A1 {
using A::i, A::i; // OK: double declaration
}
struct B {
int i;
};
struct X : B {
using B::i, B::i; // error: double member declaration
}; — end example
namespace A {
void f(int);
}
using A::f; // f is a synonym for A::f; that is, for A::f(int).
namespace A {
void f(char);
}
void foo() {
f('a'); // calls f(int), even though f(char) exists.
}
void bar() {
using A::f; // f is a synonym for A::f; that is, for A::f(int) and A::f(char).
f('a'); // calls f(char)
} — end example
namespace A {
int x;
}
namespace B {
int i;
struct g { };
struct x { };
void f(int);
void f(double);
void g(char); // OK: hides struct g
}
void func() {
int i;
using B::i; // error: i declared twice
void f(char);
using B::f; // OK: each f is a function
f(3.5); // calls B::f(double)
using B::g;
g('a'); // calls B::g(char)
struct g g1; // g1 has class type B::g
using B::x;
using A::x; // OK: hides struct B::x
x = 99; // assigns to A::x
struct x x1; // x1 has class type B::x
} — end example
namespace B {
void f(int);
void f(double);
}
namespace C {
void f(int);
void f(double);
void f(char);
}
void h() {
using B::f; // B::f(int) and B::f(double)
using C::f; // C::f(int), C::f(double), and C::f(char)
f('h'); // calls C::f(char)
f(1); // error: ambiguous: B::f(int) or C::f(int)?
void f(int); // error: f(int) conflicts with C::f(int) and B::f(int)
} — end example
struct B {
virtual void f(int);
virtual void f(char);
void g(int);
void h(int);
};
struct D : B {
using B::f;
void f(int); // OK: D::f(int) overrides B::f(int);
using B::g;
void g(char); // OK
using B::h;
void h(int); // OK: D::h(int) hides B::h(int)
};
void k(D* p)
{
p->f(1); // calls D::f(int)
p->f('a'); // calls B::f(char)
p->g(1); // calls B::g(int)
p->g('a'); // calls D::g(char)
}
struct B1 {
B1(int);
};
struct B2 {
B2(int);
};
struct D1 : B1, B2 {
using B1::B1;
using B2::B2;
};
D1 d1(0); // ill-formed: ambiguous
struct D2 : B1, B2 {
using B1::B1;
using B2::B2;
D2(int); // OK: D2::D2(int) hides B1::B1(int) and B2::B2(int)
};
D2 d2(0); // calls D2::D2(int)
— end example
struct A { int x(); };
struct B : A { };
struct C : A {
using A::x;
int x(int);
};
struct D : B, C {
using C::x;
int x(double);
};
int f(D* d) {
return d->x(); // error: overload resolution selects A::x, but A is an ambiguous base class
} — end example
class A {
private:
void f(char);
public:
void f(int);
protected:
void g();
};
class B : public A {
using A::f; // error: A::f(char) is inaccessible
public:
using A::g; // B::g is a public synonym for A::g
}; — end exampleusing-directive: attribute-specifier-seq using namespace nested-name-specifier namespace-name ;
namespace A {
int i;
namespace B {
namespace C {
int i;
}
using namespace A::B::C;
void f1() {
i = 5; // OK, C::i visible in B and hides A::i
}
}
namespace D {
using namespace B;
using namespace C;
void f2() {
i = 5; // ambiguous, B::C::i or A::i?
}
}
void f3() {
i = 5; // uses A::i
}
}
void f4() {
i = 5; // ill-formed; neither i is visible
} — end example
namespace M {
int i;
}
namespace N {
int i;
using namespace M;
}
void f() {
using namespace N;
i = 7; // error: both M::i and N::i are visible
}
namespace A {
int i;
}
namespace B {
int i;
int j;
namespace C {
namespace D {
using namespace A;
int j;
int k;
int a = i; // B::i hides A::i
}
using namespace D;
int k = 89; // no problem yet
int l = k; // ambiguous: C::k or D::k
int m = i; // B::i hides A::i
int n = j; // D::j hides B::j
}
} — end example
namespace A {
class X { };
extern "C" int g();
extern "C++" int h();
}
namespace B {
void X(int);
extern "C" int g();
extern "C++" int h(int);
}
using namespace A;
using namespace B;
void f() {
X(1); // error: name X found in two namespaces
g(); // OK: name g refers to the same entity
h(); // OK: overload resolution selects A::h
} — end note
namespace D {
int d1;
void f(char);
}
using namespace D;
int d1; // OK: no conflict with D::d1
namespace E {
int e;
void f(int);
}
namespace D { // namespace extension
int d2;
using namespace E;
void f(int);
}
void f() {
d1++; // error: ambiguous ::d1 or D::d1?
::d1++; // OK
D::d1++; // OK
d2++; // OK: D::d2
e++; // OK: E::e
f(1); // error: ambiguous: D::f(int) or E::f(int)?
f('a'); // OK: D::f(char)
} — end exampleasm-definition: attribute-specifier-seq asm ( string-literal ) ;
linkage-specification: extern string-literal { declaration-seq } extern string-literal declaration
complex sqrt(complex); // C++ linkage by default extern "C" { double sqrt(double); // C linkage }— end example
extern "C" // the name f1 and its function type have C language linkage; void f1(void(*pf)(int)); // pf is a pointer to a C function extern "C" typedef void FUNC(); FUNC f2; // the name f2 has C++ language linkage and the // function's type has C language linkage extern "C" FUNC f3; // the name of function f3 and the function's type have C language linkage void (*pf2)(FUNC*); // the name of the variable pf2 has C++ linkage and the type // of pf2 is “pointer to C++ function that takes one parameter of type // pointer to C function” extern "C" { static void f4(); // the name of the function f4 has internal linkage (not C language linkage) // and the function's type has C language linkage. } extern "C" void f5() { extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. } extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. void f6() { extern void f4(); // OK: Name linkage (internal) and function type linkage (C language linkage) // obtained from previous declaration. }— end example
extern "C" typedef void FUNC_c();
class C {
void mf1(FUNC_c*); // the name of the function mf1 and the member function's type have
// C++ language linkage; the parameter has type “pointer to C function”
FUNC_c mf2; // the name of the function mf2 and the member function's type have
// C++ language linkage
static FUNC_c* q; // the name of the data member q has C++ language linkage and
// the data member's type is “pointer to C function”
};
extern "C" {
class X {
void mf(); // the name of the function mf and the member function's type have
// C++ language linkage
void mf2(void(*)()); // the name of the function mf2 has C++ language linkage;
// the parameter has type “pointer to C function”
};
} — end example
int x;
namespace A {
extern "C" int f();
extern "C" int g() { return 1; }
extern "C" int h();
extern "C" int x(); // ill-formed: same name as global-space object x
}
namespace B {
extern "C" int f(); // A::f and B::f refer to the same function
extern "C" int g() { return 1; } // ill-formed, the function g with C language linkage has two definitions
}
int A::f() { return 98; } // definition for the function f with C language linkage
extern "C" int h() { return 97; } // definition for the function h with C language linkage
// A::h and ::h refer to the same function
— end exampleextern "C" double f(); static double f(); // error extern "C" int i; // declaration extern "C" { int i; // definition } extern "C" static void g(); // error— end example
attribute-specifier-seq: attribute-specifier-seq attribute-specifier
attribute-specifier: [ [ attribute-using-prefix attribute-list ] ] alignment-specifier
alignment-specifier: alignas ( type-id ... ) alignas ( constant-expression ... )
attribute-using-prefix: using attribute-namespace :
attribute-list: attribute attribute-list , attribute attribute ... attribute-list , attribute ...
attribute: attribute-token attribute-argument-clause
attribute-token: identifier attribute-scoped-token
attribute-scoped-token: attribute-namespace :: identifier
attribute-namespace: identifier
attribute-argument-clause: ( balanced-token-seq )
balanced-token-seq: balanced-token balanced-token-seq balanced-token
balanced-token: ( balanced-token-seq ) [ balanced-token-seq ] { balanced-token-seq } any token other than a parenthesis, a bracket, or a brace
[[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] void f() {} [[using CC: opt(1)]] [[CC::debug]] // same as [[CC::opt(1)]] [[CC::debug]] void g() {} [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute token void h() {}— end example
int p[10];
void f() {
int x = 42, y[5];
int(p[[x] { return x; }()]); // error: invalid attribute on a nested declarator-id and
// not a function-style cast of an element of p.
y[[] { return 2; }()] = 2; // error even though attributes are not allowed in this context.
int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute.
} — end example
struct alignas(8) S {};
struct alignas(1) U {
S s;
}; // error: U specifies an alignment that is less strict than if the alignas(1) were omitted.
— end example// Translation unit #1: struct S { int x; } s, *p = &s; // Translation unit #2: struct alignas(16) S; // error: definition of S lacks alignment, no diagnostic required extern S* p;— end example
alignas(T) alignas(A) T buffer[N];Specifying alignas(T) ensures that the final requested alignment will not be weaker than alignof(T), and therefore the program will not be ill-formed.
alignas(double) void f(); // error: alignment applied to function alignas(double) unsigned char c[sizeof(double)]; // array of characters, suitably aligned for a double extern unsigned char c[sizeof(double)]; // no alignas necessary alignas(float) extern unsigned char c[sizeof(double)]; // error: different alignment in declaration— end example
/* Translation unit A. */
struct foo { int* a; int* b; };
std::atomic<struct foo *> foo_head[10];
int foo_array[10][10];
[[carries_dependency]] struct foo* f(int i) {
return foo_head[i].load(memory_order_consume);
}
int g(int* x, int* y [[carries_dependency]]) {
return kill_dependency(foo_array[*x][*y]);
}
/* Translation unit B. */
[[carries_dependency]] struct foo* f(int i);
int g(int* x, int* y [[carries_dependency]]);
int c = 3;
void h(int i) {
struct foo* p;
p = f(i);
do_something_with(g(&c, p->a));
do_something_with(g(p->a, &c));
}
( string-literal )
struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();
void launch_missiles();
void test_missiles() {
enable_missile_safety_mode(); // warning encouraged
launch_missiles();
}
error_info &foo();
void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither
// the (reference) return type nor the function is declared nodiscard
— end example