C++ N4606(124)10.3 Virtual functions [class.virtual]p263


はじめに

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)

g++-7 --version

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

(124)10.3 Virtual functions [class.virtual]p263

p263.cpp
// N4606 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
#define msg "p263.cpp(124)10.3 Virtual functions [class.virtual]"

#include <iostream>

struct A {
virtual void f();
};
struct B : virtual A {
virtual void f();
};
struct C : B , virtual A {
using A::f;
};
void foo() {
C c;
c.f(); // calls B::f, the final overrider
c.C::f(); // calls A::f because of the using-declaration
}


struct A3 { virtual void f(); };
struct B3 : A3 { };
struct C3 : A3 { void f(); };
struct D3 : B3, C3 { }; // OK: A3::f and C3::f are the final overriders
// for the B3 and C3 subobjects, respectively

struct B4 {
virtual void f();
};
struct D4 : B4 {
void f(int);
};
struct D2 : D4 {
void f();
};

struct B5 {
virtual void f() const final;
};
struct D5 : B5 {
void f() const; // error: D::f attempts to override final B5::f
};

struct B6 {
virtual void f(int);
};
struct D6 : B6 {
virtual void f(long) override; // error: wrong signature overriding B6::f
virtual void f(int) override; // OK
};

class B7 { };
class D7 : private B7 { friend class Derived; };
struct Base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
virtual B7* vf4();
virtual B7* vf5();
void f();
};
struct No_good : public Base {
D7* vf4(); // error: B7 (base class of D) inaccessible
};
class A7;
struct Derived : public Base {
void vf1(); // virtual and overrides Base::vf1()
void vf2(int); // not virtual, hides Base::vf2()
char vf3(); // error: invalid difference in return type only
D7* vf4(); // OK: returns pointer to derived class
A7* vf5(); // error: returns pointer to incomplete class
void f();
};
void g() {
Derived d;
Base* bp = &d; // standard conversion:
// Derived* to Base*
bp->vf1(); // calls Derived::vf1()
bp->vf2(); // calls Base::vf2()
bp->f(); // calls Base::f() (not virtual)
B7* p = bp->vf4(); // calls Derived::pf() and converts the
// result to B*
Derived* dp = &d;
D7* q = dp->vf4(); // calls Derived::pf() and does not
// convert the result to B7*
dp->vf2(); // ill-formed: argument mismatch
}

struct A8 {
virtual void f();
};
struct B1a : A8 { // note non-virtual derivation
void f();
};
struct B2a : A8 {
void f();
};
struct D8 : B1a, B2a { // D has two separate A subobjects
};
void foo2() {
D8 d;
// A8* ap = &d; // would be ill-formed: ambiguous
B1a* b1p = &d;
A8* ap = b1p;
D8* dp = &d;
ap->f(); // calls D8::B1a::f
dp->f(); // ill-formed: ambiguous
}

struct A9 {
virtual void f();
};
struct VB1 : virtual A9 { // note virtual derivation
void f();
};
struct VB2 : virtual A {
void f();
};
struct Error : VB1, VB2 { // ill-formed
};
struct Okay : VB1, VB2 {
void f();
};

struct VB1a : virtual A9 { // does not declare f
};
struct Da : VB1a, VB2 {
};
void foe() {
VB1a* vb1ap = new Da;
vb1ap->f(); // calls VB2::f
}

class B9 { public: virtual void f(); };
class D9 : public B9 { public: void f(); };
void D9::f() { /* ... */ B9::f(); }
int main(){
  std::cout<< msg << std::endl;
  return EXIT_SUCCESS;
}
$ ./cppgl17.sh p263
$ clang++ p263.cpp
p263.cpp:43:6: error: declaration of 'f' overrides a 'final' function
void f() const; // error: D::f attempts to override final B5::f
     ^
p263.cpp:40:14: note: overridden virtual function is here
virtual void f() const final;
             ^
p263.cpp:50:14: error: 'f' marked 'override' but does not override any member functions
virtual void f(long) override; // error: wrong signature overriding B6::f
             ^
p263.cpp:65:5: error: invalid covariant return for virtual function: 'B7' is a private base class of 'D7'
D7* vf4(); // error: B7 (base class of D) inaccessible
    ^
p263.cpp:55:12: note: declared private here
class D7 : private B7 { friend class Derived; };
           ^~~~~~~~~~
p263.cpp:71:6: error: virtual function 'vf3' has a different return type ('char') than the function it overrides
      (which has return type 'void')
char vf3(); // error: invalid difference in return type only
~~~~ ^
p263.cpp:59:14: note: overridden virtual function is here
virtual void vf3();
        ~~~~ ^
p263.cpp:73:5: error: return type of virtual function 'vf5' is not covariant with the return type of the function it overrides
      ('A7' is incomplete)
A7* vf5(); // error: returns pointer to incomplete class
    ^
p263.cpp:67:7: note: forward declaration of 'A7'
class A7;
      ^
p263.cpp:88:5: error: too few arguments to function call, expected 1, have 0; did you mean 'Base::vf2'?
dp->vf2(); // ill-formed: argument mismatch
    ^~~
    Base::vf2
p263.cpp:58:14: note: 'Base::vf2' declared here
virtual void vf2();
             ^
p263.cpp:109:5: error: member 'f' found in multiple base classes of different types
dp->f(); // ill-formed: ambiguous
    ^
p263.cpp:95:6: note: member found by ambiguous name lookup
void f();
     ^
p263.cpp:98:6: note: member found by ambiguous name lookup
void f();
     ^
7 errors generated.

$ g++-7 p263.cpp
p263.cpp:43:6: error: virtual function 'virtual void D5::f() const'
 void f() const; // error: D::f attempts to override final B5::f
      ^
p263.cpp:40:14: error: overriding final function 'virtual void B5::f() const'
 virtual void f() const final;
              ^
p263.cpp:50:14: error: 'virtual void D6::f(long int)' marked 'override', but does not override
 virtual void f(long) override; // error: wrong signature overriding B6::f
              ^
p263.cpp:65:5: error: invalid covariant return type for 'virtual D7* No_good::vf4()'
 D7* vf4(); // error: B7 (base class of D) inaccessible
     ^~~
p263.cpp:60:13: error:   overriding 'virtual B7* Base::vf4()'
 virtual B7* vf4();
             ^~~
p263.cpp:71:6: error: conflicting return type specified for 'virtual char Derived::vf3()'
 char vf3(); // error: invalid difference in return type only
      ^~~
p263.cpp:59:14: error:   overriding 'virtual void Base::vf3()'
 virtual void vf3();
              ^~~
p263.cpp:73:5: error: invalid covariant return type for 'virtual A7* Derived::vf5()'
 A7* vf5(); // error: returns pointer to incomplete class
     ^~~
p263.cpp:61:13: error:   overriding 'virtual B7* Base::vf5()'
 virtual B7* vf5();
             ^~~
p263.cpp: In function 'void g()':
p263.cpp:88:9: error: no matching function for call to 'Derived::vf2()'
 dp->vf2(); // ill-formed: argument mismatch
         ^
p263.cpp:70:6: note: candidate: void Derived::vf2(int)
 void vf2(int); // not virtual, hides Base::vf2()
      ^~~
p263.cpp:70:6: note:   candidate expects 1 argument, 0 provided
p263.cpp: In function 'void foo2()':
p263.cpp:109:5: error: request for member 'f' is ambiguous
 dp->f(); // ill-formed: ambiguous
     ^
p263.cpp:92:14: note: candidates are: virtual void A8::f()
 virtual void f();
              ^
p263.cpp:98:6: note:                 virtual void B2a::f()
 void f();
      ^
p263.cpp:95:6: note:                 virtual void B1a::f()
 void f();

検討事項

コンパイルエラーの出ない修正方法。
意味のある出力。

参考資料

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