C++N4606(191)14.6.1 Locally declared names [temp.local] p381


はじめに

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.

(191)14.6.1 Locally declared names [temp.local] p381

p381.cpp
// N4606 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
#define msg "(191)14.6.1 Locally declared names [temp.local] p381.cpp"
// Edited by Dr. Ogawa Kiyoshi. Compile procedure and results record.

#include <iostream>


template<template<class> class T> class A { };
template<class T> class Y;
template<> class Y<int> {
  Y* p; // meaning Y<int>
  Y<char>* q; // meaning Y<char>
  A<Y>* a; // meaning A<::Y>
  class B {
    template<class> friend class Y; // meaning ::Y
  };
};

template <class T> struct Base {
  Base* p;
};
template <class T> struct Derived: public Base<T> {
  typename Derived::Base* p; // meaning Derived::Base<T>
};
template<class T, template<class> class U = T::template Base> struct Third { };
Third<Base<int> > t; // OK: default argument uses injected-class-name as a template

template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char> {
  typename Derived::Base b; // error: ambiguous
  typename Derived::Base<double> d; // OK
};

template<class T> class X {
  X* p; // meaning X<T>
  X<T>* p2;
  X<int>* p3;
  ::X* p4; // error: missing template argument list
// ::X does not refer to the injected-class-name

  template<class T, int i> class Y2 {
    int T; // error: template-parameter redeclared
    void f2() {
      char T; // error: template-parameter redeclared
    }
  };
  template<class X2> class X2; // error: template-parameter redeclared

  template<class T> struct A3 {
    struct B3 { /* ... */
    };
    typedef void C3;
    void f3();
    template<class U> void g3(U);
  };
  template<class B3> void A3<B3>::f() {
    B3 b; // A3’s B3, not the template parameter
  }
  template<class B3> template<class C3> void A3<B3>::g(C3) {
    B3 b; // A3’s B3, not the template parameter
    C3 c; // the template parameter C, not A’s C
  }

  namespace N {
  class C4 { };
  template<class T> class B4 {
    void f4(T);
  };
  }
  template<class C4> void N::4B<C4>::f4(C4) {
    C4 b; // C is the template parameter, not N::C
  }

  struct A5 {
    struct B5 { /* ... */
    };
    int a5;
    int Y5;
  };
  template<class B5, class a5> struct X5 : A5 {
    B5 b5; // A’s B
    a5 b5; // error: A5’s a isn’t a type name
  };


  int main() {
    std::cout<< msg << std::endl;
    return EXIT_SUCCESS;
  }
$ ./cppgl17.sh p381
$ clang++ p381.cpp
p381.cpp:26:57: warning: ISO C++ specifies that qualified reference to 'Base' is a constructor name rather than a template name in this
      context, despite preceding 'template' keyword [-Winjected-class-name]
template<class T, template<class> class U = T::template Base> struct Third { };
                                                        ^
p381.cpp:27:1: note: in instantiation of default argument for 'Third<Base<int> >' required here
Third<Base<int> > t; // OK: default argument uses injected-class-name as a template
^~~~~~~~~~~~~~~~~
p381.cpp:26:57: warning: ISO C++ specifies that qualified reference to 'Base' is a constructor name rather than a template name in this
      context, despite preceding 'template' keyword [-Winjected-class-name]
template<class T, template<class> class U = T::template Base> struct Third { };
                                                        ^
p381.cpp:27:1: note: while substituting prior template arguments into template template parameter 'U' [with T = Base<int>]
Third<Base<int> > t; // OK: default argument uses injected-class-name as a template
^~~~~~~~~~~~~~~~~
p381.cpp:27:17: note: while checking a default template argument used here
Third<Base<int> > t; // OK: default argument uses injected-class-name as a template
~~~~~~~~~~~~~~~~^
p381.cpp:29:27: error: redefinition of 'Base'
template <class T> struct Base { };
                          ^
p381.cpp:20:27: note: previous definition is here
template <class T> struct Base {
                          ^
p381.cpp:30:27: error: redefinition of 'Derived'
template <class T> struct Derived: Base<int>, Base<char> {
                          ^
p381.cpp:23:27: note: previous definition is here
template <class T> struct Derived: public Base<T> {
                          ^
p381.cpp:39:1: error: use of class template 'X' requires template arguments; argument deduction not allowed in non-static class member
::X* p4; // error: missing template argument list
^~
p381.cpp:35:25: note: template is declared here
template<class T> class X {
                        ^
p381.cpp:42:16: error: declaration of 'T' shadows template parameter
template<class T, int i> class Y2 {
               ^
p381.cpp:35:16: note: template parameter is declared here
template<class T> class X {
               ^
p381.cpp:43:5: error: declaration of 'T' shadows template parameter
int T; // error: template-parameter redeclared
    ^
p381.cpp:42:16: note: template parameter is declared here
template<class T, int i> class Y2 {
               ^
p381.cpp:48:26: error: declaration of 'X2' shadows template parameter
template<class X2> class X2; // error: template-parameter redeclared
                         ^
p381.cpp:48:16: note: template parameter is declared here
template<class X2> class X2; // error: template-parameter redeclared
               ^
p381.cpp:50:16: error: declaration of 'T' shadows template parameter
template<class T> struct A3 {
               ^
p381.cpp:35:16: note: template parameter is declared here
template<class T> class X {
               ^
p381.cpp:56:33: error: non-friend class member 'f' cannot have a qualified name
template<class B3> void A3<B3>::f() {
                        ~~~~~~~~^
p381.cpp:59:52: error: non-friend class member 'g' cannot have a qualified name
template<class B3> template<class C3> void A3<B3>::g(C3) {
                                           ~~~~~~~~^
p381.cpp:59:1: error: extraneous template parameter list in template specialization or out-of-line template definition
template<class B3> template<class C3> void A3<B3>::g(C3) {
^~~~~~~~~~~~~~~~~~
p381.cpp:35:25: error: missing '}' at end of definition of 'X'
template<class T> class X {
                        ^
p381.cpp:64:1: note: still within definition of 'X' here
namespace N {
^
p381.cpp:61:4: error: variable has incomplete type 'X::A3::C3' (aka 'void')
C3 c; // the template parameter C, not A’s C
   ^
p381.cpp:70:28: error: expected unqualified-id
template<class C4> void N::4B<C4>::f4(C4) {
                           ^
p381.cpp:79:42: error: expected class name
template<class B5, class a5> struct X5 : A5 {
                                         ^
p381.cpp:81:4: error: duplicate member 'b5'
a5 b5; // error: A5’s a isn’t a type name
   ^
p381.cpp:80:4: note: previous declaration is here
B5 b5; // A’s B
   ^
2 warnings and 15 errors generated.

$ g++-7 p381.cpp
p381.cpp:29:27: error: redefinition of 'struct Base<T>'
 template <class T> struct Base { };
                           ^~~~
p381.cpp:20:27: note: previous definition of 'struct Base<T>'
 template <class T> struct Base {
                           ^~~~
p381.cpp:30:27: error: redefinition of 'struct Derived<T>'
 template <class T> struct Derived: Base<int>, Base<char> {
                           ^~~~~~~
p381.cpp:23:27: note: previous definition of 'struct Derived<T>'
 template <class T> struct Derived: public Base<T> {
                           ^~~~~~~
p381.cpp:39:1: error: template placeholder type 'X' must be followed by a simple declarator-id
 ::X* p4; // error: missing template argument list
 ^~
p381.cpp:35:25: note: 'template<class T> class X' declared here
 template<class T> class X {
                         ^
p381.cpp:39:1: error: invalid use of template-name 'X' without an argument list
 ::X* p4; // error: missing template argument list
 ^~
p381.cpp:42:10: error: declaration of template parameter 'T' shadows template parameter
 template<class T, int i> class Y2 {
          ^~~~~
p381.cpp:35:10: note: template parameter 'T' declared here
 template<class T> class X {
          ^~~~~
p381.cpp:43:5: error: declaration of 'int X<T>::Y2<T, i>::T' shadows template parameter
 int T; // error: template-parameter redeclared
     ^
p381.cpp:42:10: note: template parameter 'T' declared here
 template<class T, int i> class Y2 {
          ^~~~~
p381.cpp:48:26: error: using template type parameter 'X2' after 'class'
 template<class X2> class X2; // error: template-parameter redeclared
                          ^~
p381.cpp:50:10: error: declaration of template parameter 'T' shadows template parameter
 template<class T> struct A3 {
          ^~~~~
p381.cpp:35:10: note: template parameter 'T' declared here
 template<class T> class X {
          ^~~~~
p381.cpp:56:25: error: specializing member 'X<T>::A3<T>::f' requires 'template<>' syntax
 template<class B3> void A3<B3>::f() {
                         ^~~~~~
p381.cpp:59:56: error: cannot define member function 'X<T>::A3<T>::g' within 'X<T>'
 template<class B3> template<class C3> void A3<B3>::g(C3) {
                                                        ^
p381.cpp:64:1: error: expected unqualified-id before 'namespace'
 namespace N {
 ^~~~~~~~~
p381.cpp:70:25: error: 'N' has not been declared
 template<class C4> void N::4B<C4>::f4(C4) {
                         ^
p381.cpp:70:28: error: expected unqualified-id before numeric constant
 template<class C4> void N::4B<C4>::f4(C4) {
                            ^~
p381.cpp:81:4: error: redeclaration of 'a5 X<T>::X5<B5, a5>::b5'
 a5 b5; // error: A5’s a isn’t a type name
    ^~
p381.cpp:80:4: note: previous declaration 'B5 X<T>::X5<B5, a5>::b5'
 B5 b5; // A’s B
    ^~
p381.cpp:88:1: error: expected '}' at end of input
 }
 ^
p381.cpp: In member function 'void X<T>::Y2<T, i>::f2()':
p381.cpp:45:6: error: declaration of 'char T' shadows template parameter
 char T; // error: template-parameter redeclared
      ^
p381.cpp:42:10: note: template parameter 'T' declared here
 template<class T, int i> class Y2 {
          ^~~~~
p381.cpp: At global scope:
p381.cpp:88:1: error: expected ';' at end of input
 }
 ^

タブを2つの空白に変換しているスクリプトは下記。

a.sh
#!/bin/bash
astyle -s2 -c < $1.cpp > $1s2.cpp
cat $1s2.cpp

検討事項

役に立つまたは意味のある出力

参考資料

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 初稿 2080420