tmp/tmphattzasp/{from.md → to.md}
RENAMED
|
@@ -14,13 +14,13 @@ A member of a class can be
|
|
| 14 |
[*Note 1*: A constructor or destructor can be named by an expression
|
| 15 |
[[basic.def.odr]] even though it has no name. — *end note*]
|
| 16 |
|
| 17 |
A member of a class can also access all the members to which the class
|
| 18 |
has access. A local class of a member function may access the same
|
| 19 |
-
members that the member function itself may access.[^
|
| 20 |
|
| 21 |
-
Members of a class defined with the keyword `class` are
|
| 22 |
default. Members of a class defined with the keywords `struct` or
|
| 23 |
`union` are public by default.
|
| 24 |
|
| 25 |
[*Example 1*:
|
| 26 |
|
|
@@ -63,14 +63,15 @@ void g(S* sp) {
|
|
| 63 |
— *end example*]
|
| 64 |
|
| 65 |
[*Note 3*:
|
| 66 |
|
| 67 |
Because access control applies to the declarations named, if access
|
| 68 |
-
control is applied to a
|
| 69 |
typedef or alias declaration itself is considered. The accessibility of
|
| 70 |
-
the entity
|
| 71 |
-
|
|
|
|
| 72 |
|
| 73 |
``` cpp
|
| 74 |
class A {
|
| 75 |
class B { };
|
| 76 |
public:
|
|
@@ -81,10 +82,12 @@ void f() {
|
|
| 81 |
A::BB x; // OK, typedef A::BB is public
|
| 82 |
A::B y; // access error, A::B is private
|
| 83 |
}
|
| 84 |
```
|
| 85 |
|
|
|
|
|
|
|
| 86 |
— *end note*]
|
| 87 |
|
| 88 |
[*Note 4*: Access control does not prevent members from being found by
|
| 89 |
name lookup or implicit conversions to base classes from being
|
| 90 |
considered. — *end note*]
|
|
@@ -100,26 +103,26 @@ and, if the entity is a class, the definitions of members of the class
|
|
| 100 |
appearing outside the class’s *member-specification*.
|
| 101 |
|
| 102 |
[*Note 5*: This access also applies to implicit references to
|
| 103 |
constructors, conversion functions, and destructors. — *end note*]
|
| 104 |
|
| 105 |
-
[*Example
|
| 106 |
|
| 107 |
``` cpp
|
| 108 |
class A {
|
| 109 |
typedef int I; // private member
|
| 110 |
-
I f();
|
| 111 |
-
friend I g(I);
|
| 112 |
static I x;
|
| 113 |
template<int> struct Q;
|
| 114 |
template<int> friend struct R;
|
| 115 |
protected:
|
| 116 |
struct B { };
|
| 117 |
};
|
| 118 |
|
| 119 |
-
A::I A::f() { return 0; }
|
| 120 |
-
A::I g(A::I p = A::x);
|
| 121 |
A::I g(A::I p) { return 0; }
|
| 122 |
A::I A::x = 0;
|
| 123 |
template<A::I> struct A::Q { };
|
| 124 |
template<A::I> struct R { };
|
| 125 |
|
|
@@ -144,11 +147,11 @@ and in member functions of class templates is performed as described in
|
|
| 144 |
[[temp.inst]].
|
| 145 |
|
| 146 |
Access for a default *template-argument* [[temp.param]] is checked in
|
| 147 |
the context in which it appears rather than at any points of use of it.
|
| 148 |
|
| 149 |
-
[*Example
|
| 150 |
|
| 151 |
``` cpp
|
| 152 |
class B { };
|
| 153 |
template <class T> class C {
|
| 154 |
protected:
|
|
@@ -255,11 +258,11 @@ of the derived class. If a class is declared to be a base class for
|
|
| 255 |
another class using the `protected` access specifier, the public and
|
| 256 |
protected members of the base class are accessible as protected members
|
| 257 |
of the derived class. If a class is declared to be a base class for
|
| 258 |
another class using the `private` access specifier, the public and
|
| 259 |
protected members of the base class are accessible as private members of
|
| 260 |
-
the derived class.[^
|
| 261 |
|
| 262 |
In the absence of an *access-specifier* for a base class, `public` is
|
| 263 |
assumed when the derived class is defined with the *class-key* `struct`
|
| 264 |
and `private` is assumed when the class is defined with the *class-key*
|
| 265 |
`class`.
|
|
@@ -289,11 +292,13 @@ A member of a private base class can be inaccessible as inherited, but
|
|
| 289 |
accessible directly. Because of the rules on pointer conversions
|
| 290 |
[[conv.ptr]] and explicit casts
|
| 291 |
[[expr.type.conv]], [[expr.static.cast]], [[expr.cast]], a conversion
|
| 292 |
from a pointer to a derived class to a pointer to an inaccessible base
|
| 293 |
class can be ill-formed if an implicit conversion is used, but
|
| 294 |
-
well-formed if an explicit cast is used.
|
|
|
|
|
|
|
| 295 |
|
| 296 |
``` cpp
|
| 297 |
class B {
|
| 298 |
public:
|
| 299 |
int mi; // non-static member
|
|
@@ -316,10 +321,12 @@ void DD::f() {
|
|
| 316 |
::B* bp2 = (::B*)this; // OK with cast
|
| 317 |
bp2->mi = 3; // OK, access through a pointer to B.
|
| 318 |
}
|
| 319 |
```
|
| 320 |
|
|
|
|
|
|
|
| 321 |
— *end note*]
|
| 322 |
|
| 323 |
A base class `B` of `N` is *accessible* at *R*, if
|
| 324 |
|
| 325 |
- an invented public member of `B` would be a public member of `N`, or
|
|
@@ -329,11 +336,11 @@ A base class `B` of `N` is *accessible* at *R*, if
|
|
| 329 |
`N`, and an invented public member of `B` would be a private or
|
| 330 |
protected member of `P`, or
|
| 331 |
- there exists a class `S` such that `B` is a base class of `S`
|
| 332 |
accessible at *R* and `S` is a base class of `N` accessible at *R*.
|
| 333 |
|
| 334 |
-
[*Example
|
| 335 |
|
| 336 |
``` cpp
|
| 337 |
class B {
|
| 338 |
public:
|
| 339 |
int m;
|
|
@@ -360,33 +367,39 @@ derived class to a pointer to that base class
|
|
| 360 |
|
| 361 |
[*Note 2*: It follows that members and friends of a class `X` can
|
| 362 |
implicitly convert an `X*` to a pointer to a private or protected
|
| 363 |
immediate base class of `X`. — *end note*]
|
| 364 |
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
|
| 369 |
[*Note 3*: This class can be explicit, e.g., when a *qualified-id* is
|
| 370 |
used, or implicit, e.g., when a class member access operator
|
| 371 |
[[expr.ref]] is used (including cases where an implicit “`this->`” is
|
| 372 |
added). If both a class member access operator and a *qualified-id* are
|
| 373 |
-
used to name the member (as in `p->T::m`), the class
|
| 374 |
-
is the class
|
| 375 |
*qualified-id* (that is, `T`). — *end note*]
|
| 376 |
|
| 377 |
-
A member `m` is accessible at the point *R* when
|
|
|
|
| 378 |
|
|
|
|
| 379 |
- `m` as a member of `N` is public, or
|
| 380 |
- `m` as a member of `N` is private, and *R* occurs in a direct member
|
| 381 |
or friend of class `N`, or
|
| 382 |
- `m` as a member of `N` is protected, and *R* occurs in a direct member
|
| 383 |
or friend of class `N`, or in a member of a class `P` derived from
|
| 384 |
`N`, where `m` as a member of `P` is public, private, or protected, or
|
| 385 |
- there exists a base class `B` of `N` that is accessible at *R*, and
|
| 386 |
-
`m` is accessible at *R* when
|
| 387 |
-
\[*Example
|
| 388 |
``` cpp
|
| 389 |
class B;
|
| 390 |
class A {
|
| 391 |
private:
|
| 392 |
int i;
|
|
@@ -402,14 +415,14 @@ A member `m` is accessible at the point *R* when named in class `N` if
|
|
| 402 |
|
| 403 |
If a class member access operator, including an implicit “`this->`”, is
|
| 404 |
used to access a non-static data member or non-static member function,
|
| 405 |
the reference is ill-formed if the left operand (considered as a pointer
|
| 406 |
in the “`.`” operator case) cannot be implicitly converted to a pointer
|
| 407 |
-
to the
|
| 408 |
|
| 409 |
[*Note 4*: This requirement is in addition to the requirement that the
|
| 410 |
-
member be accessible as
|
| 411 |
|
| 412 |
### Friends <a id="class.friend">[[class.friend]]</a>
|
| 413 |
|
| 414 |
A friend of a class is a function or class that is given permission to
|
| 415 |
name the private and protected members of the class. A class specifies
|
|
@@ -481,31 +494,26 @@ class Z {
|
|
| 481 |
};
|
| 482 |
```
|
| 483 |
|
| 484 |
— *end example*]
|
| 485 |
|
| 486 |
-
A friend declaration that does not declare a function shall
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
``` bnf
|
| 490 |
-
friend elaborated-type-specifier ';'
|
| 491 |
-
friend simple-type-specifier ';'
|
| 492 |
-
friend typename-specifier ';'
|
| 493 |
-
```
|
| 494 |
|
| 495 |
[*Note 1*: A friend declaration can be the *declaration* in a
|
| 496 |
*template-declaration* [[temp.pre]], [[temp.friend]]. — *end note*]
|
| 497 |
|
| 498 |
-
If
|
| 499 |
-
cv-qualified) class type, that class is declared as a friend;
|
| 500 |
-
the friend
|
| 501 |
|
| 502 |
[*Example 4*:
|
| 503 |
|
| 504 |
``` cpp
|
| 505 |
class C;
|
| 506 |
typedef C Ct;
|
|
|
|
| 507 |
|
| 508 |
class X1 {
|
| 509 |
friend C; // OK, class C is a friend
|
| 510 |
};
|
| 511 |
|
|
@@ -513,24 +521,30 @@ class X2 {
|
|
| 513 |
friend Ct; // OK, class C is a friend
|
| 514 |
friend D; // error: D not found
|
| 515 |
friend class D; // OK, elaborated-type-specifier declares new class
|
| 516 |
};
|
| 517 |
|
| 518 |
-
template <typename
|
| 519 |
-
friend
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 520 |
};
|
| 521 |
|
| 522 |
R<C> rc; // class C is a friend of R<C>
|
| 523 |
-
R<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
```
|
| 525 |
|
| 526 |
— *end example*]
|
| 527 |
|
| 528 |
-
A function first declared in a friend declaration has the linkage of the
|
| 529 |
-
namespace of which it is a member [[basic.link]]. Otherwise, the
|
| 530 |
-
function retains its previous linkage [[dcl.stc]].
|
| 531 |
-
|
| 532 |
[*Note 2*:
|
| 533 |
|
| 534 |
A friend declaration refers to an entity, not (all overloads of) a name.
|
| 535 |
A member function of a class `X` can be a friend of a class `Y`.
|
| 536 |
|
|
@@ -671,12 +685,12 @@ void f() {
|
|
| 671 |
|
| 672 |
### Protected member access <a id="class.protected">[[class.protected]]</a>
|
| 673 |
|
| 674 |
An additional access check beyond those described earlier in
|
| 675 |
[[class.access]] is applied when a non-static data member or non-static
|
| 676 |
-
member function is a protected member of its
|
| 677 |
-
[[class.access.base]].[^
|
| 678 |
|
| 679 |
As described earlier, access to a protected member is granted because
|
| 680 |
the reference occurs in a friend or direct member of some class `C`. If
|
| 681 |
the access is to form a pointer to member [[expr.unary.op]], the
|
| 682 |
*nested-name-specifier* shall denote `C` or a class derived from `C`.
|
|
@@ -703,14 +717,14 @@ class D2 : public B {
|
|
| 703 |
|
| 704 |
void fr(B* pb, D1* p1, D2* p2) {
|
| 705 |
pb->i = 1; // error
|
| 706 |
p1->i = 2; // error
|
| 707 |
p2->i = 3; // OK (access through a D2)
|
| 708 |
-
p2->B::i = 4; // OK (access through a D2, even though
|
| 709 |
int B::* pmi_B = &B::i; // error
|
| 710 |
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
|
| 711 |
-
B::j = 5; // error: not a friend of
|
| 712 |
D2::j = 6; // OK (because refers to static member)
|
| 713 |
}
|
| 714 |
|
| 715 |
void D2::mem(B* pb, D1* p1) {
|
| 716 |
pb->i = 1; // error
|
|
|
|
| 14 |
[*Note 1*: A constructor or destructor can be named by an expression
|
| 15 |
[[basic.def.odr]] even though it has no name. — *end note*]
|
| 16 |
|
| 17 |
A member of a class can also access all the members to which the class
|
| 18 |
has access. A local class of a member function may access the same
|
| 19 |
+
members that the member function itself may access.[^9]
|
| 20 |
|
| 21 |
+
Members of a class defined with the keyword `class` are private by
|
| 22 |
default. Members of a class defined with the keywords `struct` or
|
| 23 |
`union` are public by default.
|
| 24 |
|
| 25 |
[*Example 1*:
|
| 26 |
|
|
|
|
| 63 |
— *end example*]
|
| 64 |
|
| 65 |
[*Note 3*:
|
| 66 |
|
| 67 |
Because access control applies to the declarations named, if access
|
| 68 |
+
control is applied to a type alias, only the accessibility of the
|
| 69 |
typedef or alias declaration itself is considered. The accessibility of
|
| 70 |
+
the underlying entity is not considered.
|
| 71 |
+
|
| 72 |
+
[*Example 3*:
|
| 73 |
|
| 74 |
``` cpp
|
| 75 |
class A {
|
| 76 |
class B { };
|
| 77 |
public:
|
|
|
|
| 82 |
A::BB x; // OK, typedef A::BB is public
|
| 83 |
A::B y; // access error, A::B is private
|
| 84 |
}
|
| 85 |
```
|
| 86 |
|
| 87 |
+
— *end example*]
|
| 88 |
+
|
| 89 |
— *end note*]
|
| 90 |
|
| 91 |
[*Note 4*: Access control does not prevent members from being found by
|
| 92 |
name lookup or implicit conversions to base classes from being
|
| 93 |
considered. — *end note*]
|
|
|
|
| 103 |
appearing outside the class’s *member-specification*.
|
| 104 |
|
| 105 |
[*Note 5*: This access also applies to implicit references to
|
| 106 |
constructors, conversion functions, and destructors. — *end note*]
|
| 107 |
|
| 108 |
+
[*Example 4*:
|
| 109 |
|
| 110 |
``` cpp
|
| 111 |
class A {
|
| 112 |
typedef int I; // private member
|
| 113 |
+
I f() pre(A::x > 0);
|
| 114 |
+
friend I g(I) post(A::x <= 0);
|
| 115 |
static I x;
|
| 116 |
template<int> struct Q;
|
| 117 |
template<int> friend struct R;
|
| 118 |
protected:
|
| 119 |
struct B { };
|
| 120 |
};
|
| 121 |
|
| 122 |
+
A::I A::f() pre(A::x > 0) { return 0; }
|
| 123 |
+
A::I g(A::I p = A::x) post(A::x <= 0);
|
| 124 |
A::I g(A::I p) { return 0; }
|
| 125 |
A::I A::x = 0;
|
| 126 |
template<A::I> struct A::Q { };
|
| 127 |
template<A::I> struct R { };
|
| 128 |
|
|
|
|
| 147 |
[[temp.inst]].
|
| 148 |
|
| 149 |
Access for a default *template-argument* [[temp.param]] is checked in
|
| 150 |
the context in which it appears rather than at any points of use of it.
|
| 151 |
|
| 152 |
+
[*Example 5*:
|
| 153 |
|
| 154 |
``` cpp
|
| 155 |
class B { };
|
| 156 |
template <class T> class C {
|
| 157 |
protected:
|
|
|
|
| 258 |
another class using the `protected` access specifier, the public and
|
| 259 |
protected members of the base class are accessible as protected members
|
| 260 |
of the derived class. If a class is declared to be a base class for
|
| 261 |
another class using the `private` access specifier, the public and
|
| 262 |
protected members of the base class are accessible as private members of
|
| 263 |
+
the derived class.[^10]
|
| 264 |
|
| 265 |
In the absence of an *access-specifier* for a base class, `public` is
|
| 266 |
assumed when the derived class is defined with the *class-key* `struct`
|
| 267 |
and `private` is assumed when the class is defined with the *class-key*
|
| 268 |
`class`.
|
|
|
|
| 292 |
accessible directly. Because of the rules on pointer conversions
|
| 293 |
[[conv.ptr]] and explicit casts
|
| 294 |
[[expr.type.conv]], [[expr.static.cast]], [[expr.cast]], a conversion
|
| 295 |
from a pointer to a derived class to a pointer to an inaccessible base
|
| 296 |
class can be ill-formed if an implicit conversion is used, but
|
| 297 |
+
well-formed if an explicit cast is used.
|
| 298 |
+
|
| 299 |
+
[*Example 2*:
|
| 300 |
|
| 301 |
``` cpp
|
| 302 |
class B {
|
| 303 |
public:
|
| 304 |
int mi; // non-static member
|
|
|
|
| 321 |
::B* bp2 = (::B*)this; // OK with cast
|
| 322 |
bp2->mi = 3; // OK, access through a pointer to B.
|
| 323 |
}
|
| 324 |
```
|
| 325 |
|
| 326 |
+
— *end example*]
|
| 327 |
+
|
| 328 |
— *end note*]
|
| 329 |
|
| 330 |
A base class `B` of `N` is *accessible* at *R*, if
|
| 331 |
|
| 332 |
- an invented public member of `B` would be a public member of `N`, or
|
|
|
|
| 336 |
`N`, and an invented public member of `B` would be a private or
|
| 337 |
protected member of `P`, or
|
| 338 |
- there exists a class `S` such that `B` is a base class of `S`
|
| 339 |
accessible at *R* and `S` is a base class of `N` accessible at *R*.
|
| 340 |
|
| 341 |
+
[*Example 3*:
|
| 342 |
|
| 343 |
``` cpp
|
| 344 |
class B {
|
| 345 |
public:
|
| 346 |
int m;
|
|
|
|
| 367 |
|
| 368 |
[*Note 2*: It follows that members and friends of a class `X` can
|
| 369 |
implicitly convert an `X*` to a pointer to a private or protected
|
| 370 |
immediate base class of `X`. — *end note*]
|
| 371 |
|
| 372 |
+
An expression E that designates a member `m` has a *designating class*
|
| 373 |
+
that affects the access to `m`. This designating class is either
|
| 374 |
+
|
| 375 |
+
- the innermost class of which `m` is directly a member if E is a
|
| 376 |
+
*splice-expression* or
|
| 377 |
+
- the class in whose scope name lookup performed a search that found `m`
|
| 378 |
+
otherwise.
|
| 379 |
|
| 380 |
[*Note 3*: This class can be explicit, e.g., when a *qualified-id* is
|
| 381 |
used, or implicit, e.g., when a class member access operator
|
| 382 |
[[expr.ref]] is used (including cases where an implicit “`this->`” is
|
| 383 |
added). If both a class member access operator and a *qualified-id* are
|
| 384 |
+
used to name the member (as in `p->T::m`), the class designating the
|
| 385 |
+
member is the class designated by the *nested-name-specifier* of the
|
| 386 |
*qualified-id* (that is, `T`). — *end note*]
|
| 387 |
|
| 388 |
+
A member `m` is accessible at the point *R* when designated in class `N`
|
| 389 |
+
if
|
| 390 |
|
| 391 |
+
- `m` is designated by a *splice-expression*, or
|
| 392 |
- `m` as a member of `N` is public, or
|
| 393 |
- `m` as a member of `N` is private, and *R* occurs in a direct member
|
| 394 |
or friend of class `N`, or
|
| 395 |
- `m` as a member of `N` is protected, and *R* occurs in a direct member
|
| 396 |
or friend of class `N`, or in a member of a class `P` derived from
|
| 397 |
`N`, where `m` as a member of `P` is public, private, or protected, or
|
| 398 |
- there exists a base class `B` of `N` that is accessible at *R*, and
|
| 399 |
+
`m` is accessible at *R* when designated in class `B`.
|
| 400 |
+
\[*Example 4*:
|
| 401 |
``` cpp
|
| 402 |
class B;
|
| 403 |
class A {
|
| 404 |
private:
|
| 405 |
int i;
|
|
|
|
| 415 |
|
| 416 |
If a class member access operator, including an implicit “`this->`”, is
|
| 417 |
used to access a non-static data member or non-static member function,
|
| 418 |
the reference is ill-formed if the left operand (considered as a pointer
|
| 419 |
in the “`.`” operator case) cannot be implicitly converted to a pointer
|
| 420 |
+
to the designating class of the right operand.
|
| 421 |
|
| 422 |
[*Note 4*: This requirement is in addition to the requirement that the
|
| 423 |
+
member be accessible as designated. — *end note*]
|
| 424 |
|
| 425 |
### Friends <a id="class.friend">[[class.friend]]</a>
|
| 426 |
|
| 427 |
A friend of a class is a function or class that is given permission to
|
| 428 |
name the private and protected members of the class. A class specifies
|
|
|
|
| 494 |
};
|
| 495 |
```
|
| 496 |
|
| 497 |
— *end example*]
|
| 498 |
|
| 499 |
+
A friend declaration that does not declare a function shall be a
|
| 500 |
+
*friend-type-declaration*.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 501 |
|
| 502 |
[*Note 1*: A friend declaration can be the *declaration* in a
|
| 503 |
*template-declaration* [[temp.pre]], [[temp.friend]]. — *end note*]
|
| 504 |
|
| 505 |
+
If a *friend-type-specifier* in a friend declaration designates a
|
| 506 |
+
(possibly cv-qualified) class type, that class is declared as a friend;
|
| 507 |
+
otherwise, the *friend-type-specifier* is ignored.
|
| 508 |
|
| 509 |
[*Example 4*:
|
| 510 |
|
| 511 |
``` cpp
|
| 512 |
class C;
|
| 513 |
typedef C Ct;
|
| 514 |
+
class E;
|
| 515 |
|
| 516 |
class X1 {
|
| 517 |
friend C; // OK, class C is a friend
|
| 518 |
};
|
| 519 |
|
|
|
|
| 521 |
friend Ct; // OK, class C is a friend
|
| 522 |
friend D; // error: D not found
|
| 523 |
friend class D; // OK, elaborated-type-specifier declares new class
|
| 524 |
};
|
| 525 |
|
| 526 |
+
template <typename ... Ts> class R {
|
| 527 |
+
friend Ts...;
|
| 528 |
+
};
|
| 529 |
+
|
| 530 |
+
template <class... Ts, class... Us>
|
| 531 |
+
class R<R<Ts...>, R<Us...>> {
|
| 532 |
+
friend Ts::Nested..., Us...;
|
| 533 |
};
|
| 534 |
|
| 535 |
R<C> rc; // class C is a friend of R<C>
|
| 536 |
+
R<C, E> rce; // classes C and E are friends of R<C, E>
|
| 537 |
+
R<int> Ri; // OK, ``friend int;'' is ignored
|
| 538 |
+
|
| 539 |
+
struct E { struct Nested; };
|
| 540 |
+
|
| 541 |
+
R<R<E>, R<C, int>> rr; // E::Nested and C are friends of R<R<E>, R<C, int>>
|
| 542 |
```
|
| 543 |
|
| 544 |
— *end example*]
|
| 545 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 546 |
[*Note 2*:
|
| 547 |
|
| 548 |
A friend declaration refers to an entity, not (all overloads of) a name.
|
| 549 |
A member function of a class `X` can be a friend of a class `Y`.
|
| 550 |
|
|
|
|
| 685 |
|
| 686 |
### Protected member access <a id="class.protected">[[class.protected]]</a>
|
| 687 |
|
| 688 |
An additional access check beyond those described earlier in
|
| 689 |
[[class.access]] is applied when a non-static data member or non-static
|
| 690 |
+
member function is a protected member of its designating class
|
| 691 |
+
[[class.access.base]].[^11]
|
| 692 |
|
| 693 |
As described earlier, access to a protected member is granted because
|
| 694 |
the reference occurs in a friend or direct member of some class `C`. If
|
| 695 |
the access is to form a pointer to member [[expr.unary.op]], the
|
| 696 |
*nested-name-specifier* shall denote `C` or a class derived from `C`.
|
|
|
|
| 717 |
|
| 718 |
void fr(B* pb, D1* p1, D2* p2) {
|
| 719 |
pb->i = 1; // error
|
| 720 |
p1->i = 2; // error
|
| 721 |
p2->i = 3; // OK (access through a D2)
|
| 722 |
+
p2->B::i = 4; // OK (access through a D2, even though designating class is B)
|
| 723 |
int B::* pmi_B = &B::i; // error
|
| 724 |
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
|
| 725 |
+
B::j = 5; // error: not a friend of designating class B
|
| 726 |
D2::j = 6; // OK (because refers to static member)
|
| 727 |
}
|
| 728 |
|
| 729 |
void D2::mem(B* pb, D1* p1) {
|
| 730 |
pb->i = 1; // error
|