C++ N4606(129)11.3 Friends [class.friend]p274


はじめに

N4606 Working Draft, Standard for Programming Language C++
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/#mailing2016-11
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf

n4606は、ISO/IEC JTC1 SC22 WG21の作業原案(Working Draft)です。
公式のISO/IEC 14882原本ではありません。
ISO/IEC JTC1 SC22 WG21では、可能な限り作業文書を公開し、幅広い意見を求めています。
一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(g++, Clang++)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C++, MISRA C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, TOPPERSカーネル、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。

作業方針

1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。

1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。

list

N4606 Working Draft 2016, ISO/IEC 14882, C++ standard(1) coding list
https://qiita.com/kaizen_nagoya/items/df5d62c35bd6ed1c3d43/

Compiler

clang++ --version

clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-apple-darwin17.4.0

g++-7 --version

g++-7 (Homebrew GCC 7.3.0_1) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.

(129)11.3 Friends [class.friend]p274

p274.cpp
// N4606 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
#define msg "p274.cpp(129)11.3 Friends [class.friend]"

#include <iostream>

class X {
  int a;
  friend void friend_set(X*, int);
public:
  void member_set(int);
};
void friend_set(X* p, int i) {
  p->a = i;
}
void X::member_set(int i) {
  a = i;
}
void f() {
  X obj;
  friend_set(&obj,10);
  obj.member_set(10);
}

class A {
  class B { };
  friend class X3;
};
struct X3 : A::B { // OK: A::B accessible to friend
  A::B mx; // OK: A::B accessible to member of friend
  class Y {
    A::B my; // OK: A::B accessible to nested member of friend
  };
};


class X4 {
  enum { a=100 };
  friend class Y3;
};
class Y4 {
  int v[X4::a]; // OK, Y4 is a friend of X4
};
class Z4 {
  int v[X4::a]; // error: X4::a is private
};


class A3 {
  friend class B3 { }; // error: cannot define class in friend declaration
};


class C;
typedef C Ct;
class X1 {
  friend C; // OK: class C is a friend
};
class X2 {
  friend Ct; // OK: class C is a friend
  friend D; // error: no type-name D in scope
  friend class D; // OK: elaborated-type-specifier declares new class
};
template <typename T> class R {
  friend T;
};
R<C> rc; // class C is a friend of R<C>
R<int> Ri; // OK: "friend int;" is ignored


class Y5 {
  friend char* X5::foo(int);
friend X5:
  X5(char); // constructors can be friends
  friend X5::~X5(); // destructors can be friends
};


class M {
  friend void f3() { } // definition of global f, a friend of M,
// not the definition of a member function
};


class A6 {
  friend class B6;
  int a;
};
class B6 {
  friend class C6;
};
class C6 {
  void f(A6* p) {
    p->a++; // error: C is not a friend of A6
// despite being a friend of a friend
  }
};
class D6 : public B6 {
  void f(A6* p) {
    p->a++; // error: D6 is not a friend of A6
// despite being derived from a friend
  }
};


class X7;
void a();
void f2() {
  class Y7;
  extern void b();
  class A7 {
    friend class X7; // OK, but X is a local class, not ::X7
    friend class Y7; // OK
    friend class Z7; // OK, introduces local class Z7
    friend void a(); // error, ::a is not considered
    friend void b(); // OK
    friend void c(); // error
  };
  X7* px; // OK, but ::X7 is found
  Z7* pz; // error, no 7Z is found
}

int main() {
  std::cout<< msg << std::endl;
  return EXIT_SUCCESS;
}
$ ./cppgl17.sh p129
$ clang++ p129.cpp
p129.cpp:38:11: error: 'a' is a private member of 'X4'
int v[X4::a]; // OK, Y4 is a friend of X4
          ^
p129.cpp:34:8: note: implicitly declared private here
enum { a=100 };
       ^
p129.cpp:41:11: error: 'a' is a private member of 'X4'
int v[X4::a]; // error: X4::a is private
          ^
p129.cpp:34:8: note: implicitly declared private here
enum { a=100 };
       ^
p129.cpp:46:17: error: cannot define a type in a friend declaration
friend class B3 { }; // error: cannot define class in friend declaration
~~~~~~          ^
p129.cpp:57:8: error: C++ requires a type specifier for all declarations
friend D; // error: no type-name D in scope
~~~~~~ ^
p129.cpp:57:8: error: friends can only be classes or functions
p129.cpp:68:14: error: use of undeclared identifier 'X5'
friend char* X5::foo(int);
             ^
p129.cpp:69:8: error: unknown type name 'X5'
friend X5:X5(char); // constructors can be friends
       ^
p129.cpp:69:18: error: expected '(' for function-style cast or type construction
friend X5:X5(char); // constructors can be friends
             ~~~~^
p129.cpp:69:10: error: friends can only be classes or functions
friend X5:X5(char); // constructors can be friends
         ^
p129.cpp:70:8: error: use of undeclared identifier 'X5'
friend X5::~X5(); // destructors can be friends
       ^
p129.cpp:89:4: error: 'a' is a private member of 'A6'
p->a++; // error: C is not a friend of A6
   ^
p129.cpp:82:5: note: implicitly declared private here
int a;
    ^
p129.cpp:95:4: error: 'a' is a private member of 'A6'
p->a++; // error: D6 is not a friend of A6
   ^
p129.cpp:82:5: note: implicitly declared private here
int a;
    ^
p129.cpp:110:13: error: no matching function 'a' found in local scope; did you mean '::a'?
friend void a(); // error, ::a is not considered
            ^
            ::a
p129.cpp:102:6: note: '::a' declared here
void a();
     ^
p129.cpp:112:13: error: no matching function found in local scope
friend void c(); // error
            ^
p129.cpp:115:1: error: unknown type name 'Z7'
Z7* pz; // error, no 7Z is found
^
15 errors generated.

$ g++-7 p129.cpp
p129.cpp:38:11: error: 'X4::<unnamed enum> a' is private within this context
 int v[X4::a]; // OK, Y4 is a friend of X4
           ^
p129.cpp:34:8: note: declared private here
 enum { a=100 };
        ^
p129.cpp:41:11: error: 'X4::<unnamed enum> a' is private within this context
 int v[X4::a]; // error: X4::a is private
           ^
p129.cpp:34:8: note: declared private here
 enum { a=100 };
        ^
p129.cpp:46:1: error: class definition may not be declared a friend
 friend class B3 { }; // error: cannot define class in friend declaration
 ^~~~~~
p129.cpp:57:8: error: 'D' does not name a type
 friend D; // error: no type-name D in scope
        ^
p129.cpp:68:14: error: 'X5' has not been declared
 friend char* X5::foo(int);
              ^~
p129.cpp:69:8: error: 'X5' does not name a type; did you mean 'Y5'?
 friend X5:X5(char); // constructors can be friends
        ^~
        Y5
p129.cpp:70:8: error: 'X5' does not name a type; did you mean 'Y5'?
 friend X5::~X5(); // destructors can be friends
        ^~
        Y5
p129.cpp: In member function 'void C6::f(A6*)':
p129.cpp:89:4: error: 'int A6::a' is private within this context
 p->a++; // error: C is not a friend of A6
    ^
p129.cpp:82:5: note: declared private here
 int a;
     ^
p129.cpp: In member function 'void D6::f(A6*)':
p129.cpp:95:4: error: 'int A6::a' is private within this context
 p->a++; // error: D6 is not a friend of A6
    ^
p129.cpp:82:5: note: declared private here
 int a;
     ^
p129.cpp: In function 'void f2()':
p129.cpp:110:15: error: friend declaration 'void a()' in local class without prior declaration
 friend void a(); // error, ::a is not considered
               ^
p129.cpp:112:15: error: friend declaration 'void c()' in local class without prior declaration
 friend void c(); // error
               ^
p129.cpp:115:1: error: 'Z7' was not declared in this scope
 Z7* pz; // error, no 7Z is found
 ^~
p129.cpp:115:5: error: 'pz' was not declared in this scope
 Z7* pz; // error, no 7Z is found
     ^~
p129.cpp:115:5: note: suggested alternative: 'px'
 Z7* pz; // error, no 7Z is found
     ^~
     px

検討事項

コンパイルエラーをなくす修正
意味のある出力

参考資料

N4606 Working Draft 2016, ISO/IEC 14882, C++ standardのコード断片をコンパイルするためにしていること
https://qiita.com/kaizen_nagoya/items/a8d7ee2f2e29e76c19c1

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

Clang/Clang++(LLVM) gcc/g++(GNU) コンパイラ警告等比較
https://qiita.com/kaizen_nagoya/items/9a82b958cc3aeef0403f

Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d

MISRA C++ 5-0-16
https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74

C++ Templates Part1 BASICS Chapter 3. Class Templates 3.2 Use of Class Template Stack stack1test.cpp
https://qiita.com/kaizen_nagoya/items/cd5fc49106fad5a4e9ed

ISO/IEC TS 17961:2013 C Secure Coding Rules(1) All list(to be confirmed)
https://qiita.com/kaizen_nagoya/items/54e056195c4f11b850a1

C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a

C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9

'wchar.h' file not found で困った clang++ macOS
https://qiita.com/kaizen_nagoya/items/de15cd46d657517fac11

Open POSIX Test Suiteの使い方を調べはじめました
https://qiita.com/kaizen_nagoya/items/644d5e407f5faf96e6dc

MISRA-C 2012 Referenceに掲載している文献の入手可能性を確認
https://qiita.com/kaizen_nagoya/items/96dc8b125e462d5575bb

どうやって MISRA Example Suiteをコンパイルするか
https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00

MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

「C++完全理解ガイド」の同意できること上位10
https://qiita.com/kaizen_nagoya/items/aa5744e0c4a8618c7671

文書履歴

0.10 初稿 2080419