C++
coding
14882

N4606 Working Draft 2016, ISO/IEC 14882, C++ standard(27)3.9 Types [basic.types] p74

はじめに

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++が標準化の動きとの時間的な擦れの確認が結果としてできれば幸いです。

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.

(27)3.9 Types [basic.types]
p74

p74.cpp
// N4606 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf 
#define msg "p74.cpp 3.9 Types [basic.types]"

#include <iostream>
#include <cstdint>
#include <cstring>

#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
// obj might be modified
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
// holds its original value

T* t1p;
T* t2p;
// provided that t2p points to an initialized object ...
std::memcpy(t1p, t2p, sizeof(T));
// at this point, every subobject of trivially copyable type in *t1p contains
// the same value as the corresponding subobject in *t2p

class X; // X is an incomplete type
extern X* xp; // xp is a pointer to an incomplete type
extern int arr[]; // the type of arr is incomplete
typedef int UNKA[]; // UNKA is an incomplete type
UNKA* arrp; // arrp is a pointer to an incomplete type
UNKA** arrpp;
void foo() {
  xp++; // ill-formed: X is incomplete
  arrp++; // ill-formed: incomplete type
  arrpp++; // OK: sizeof UNKA* is known
}
struct X { int i; }; // now X is a complete type
int arr[10]; // now the type of arr is complete
X x;
void bar() {
  xp = &x; // OK; type is “pointer to X”
  arrp = &arr; // ill-formed: different types
  xp++; // OK: X is complete
  arrp++; // ill-formed: UNKA can’t be completed
}

int main(int argc, char *argv[], char *envp[]){
  std::cout << msg << std::endl;
  return EXIT_SUCCESS;
}
$ ./cppgl17.sh p74
$ clang++ p74.cpp
p74.cpp:10:10: error: use of undeclared identifier 'T'
char buf[N];
         ^
p74.cpp:9:18: note: expanded from macro 'N'
#define N sizeof(T)
                 ^
p74.cpp:11:1: error: unknown type name 'T'
T obj; // obj initialized to its original value
^
p74.cpp:12:6: error: C++ requires a type specifier for all declarations
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
     ^
p74.cpp:12:6: error: no member named 'memcpy' in namespace 'std'
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
~~~~~^
p74.cpp:12:24: error: use of undeclared identifier 'T'
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
                       ^
p74.cpp:9:18: note: expanded from macro 'N'
#define N sizeof(T)
                 ^
p74.cpp:14:6: error: C++ requires a type specifier for all declarations
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
     ^
p74.cpp:14:6: error: no member named 'memcpy' in namespace 'std'
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
~~~~~^
p74.cpp:14:24: error: use of undeclared identifier 'T'
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
                       ^
p74.cpp:9:18: note: expanded from macro 'N'
#define N sizeof(T)
                 ^
p74.cpp:17:1: error: unknown type name 'T'
T* t1p;
^
p74.cpp:18:1: error: unknown type name 'T'
T* t2p;
^
p74.cpp:20:6: error: C++ requires a type specifier for all declarations
std::memcpy(t1p, t2p, sizeof(T));
     ^
p74.cpp:20:6: error: no member named 'memcpy' in namespace 'std'
std::memcpy(t1p, t2p, sizeof(T));
~~~~~^
p74.cpp:20:30: error: use of undeclared identifier 'T'
std::memcpy(t1p, t2p, sizeof(T));
                             ^
p74.cpp:31:5: error: arithmetic on a pointer to an incomplete type 'X'
  xp++; // ill-formed: X is incomplete
  ~~^
p74.cpp:24:7: note: forward declaration of 'X'
class X; // X is an incomplete type
      ^
p74.cpp:32:7: error: arithmetic on a pointer to an incomplete type 'UNKA' (aka 'int []')
  arrp++; // ill-formed: incomplete type
  ~~~~^
p74.cpp:40:10: error: assigning to 'UNKA *' (aka 'int (*)[]') from incompatible type 'int (*)[10]'
  arrp = &arr; // ill-formed: different types
         ^~~~
p74.cpp:42:7: error: arithmetic on a pointer to an incomplete type 'UNKA' (aka 'int []')
  arrp++; // ill-formed: UNKA can’t be completed
  ~~~~^
17 errors generated.

$ g++-7 p74.cpp
p74.cpp:9:18: error: 'T' was not declared in this scope
 #define N sizeof(T)
                  ^
p74.cpp:10:10: note: in expansion of macro 'N'
 char buf[N];
          ^
p74.cpp:11:1: error: 'T' does not name a type
 T obj; // obj initialized to its original value
 ^
p74.cpp:12:12: error: expected constructor, destructor, or type conversion before '(' token
 std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
            ^
p74.cpp:14:12: error: expected constructor, destructor, or type conversion before '(' token
 std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
            ^
p74.cpp:17:1: error: 'T' does not name a type
 T* t1p;
 ^
p74.cpp:18:1: error: 'T' does not name a type
 T* t2p;
 ^
p74.cpp:20:12: error: expected constructor, destructor, or type conversion before '(' token
 std::memcpy(t1p, t2p, sizeof(T));
            ^
p74.cpp: In function 'void foo()':
p74.cpp:31:5: error: cannot increment a pointer to incomplete type 'X'
   xp++; // ill-formed: X is incomplete
     ^~
p74.cpp:32:7: error: cannot increment a pointer to incomplete type 'UNKA {aka int []}'
   arrp++; // ill-formed: incomplete type
       ^~
p74.cpp: In function 'void bar()':
p74.cpp:40:11: error: cannot convert 'int (*)[10]' to 'int (*)[]' in assignment
   arrp = &arr; // ill-formed: different types
           ^~~
p74.cpp:42:7: error: cannot increment a pointer to incomplete type 'UNKA {aka int []}'
   arrp++; // ill-formed: UNKA can’t be completed
       ^~

検討事項

 コンパイルエラーにならない変更。(cstringしか手がいれれていない。)
 内容の出力。

参考資料

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da
Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d

文書履歴

0.10 初稿 2080415