diff --git a/000-preface.md b/000-preface.md new file mode 100644 index 0000000..b45af70 --- /dev/null +++ b/000-preface.md @@ -0,0 +1,7 @@ +# 序 + +本書はプログラミング経験者向けのC++入門書である。 + +本書の対象読者は、すでに何らかの実用的なプログラミング言語を習得していることを想定し、プログラミングの初歩的な概念はすべて理解しているものとして説明しない。そのため、本書には、「変数は箱のようなものである」といったような説明は出てこない。ただし、主要な他の言語とC++として特別に注意が必要な差は解説している。 + + diff --git a/001-intro.md b/001-intro.md new file mode 100644 index 0000000..d39d9a6 --- /dev/null +++ b/001-intro.md @@ -0,0 +1,33 @@ +# C++の概要 + +C++とは何か。C++の原作者にして最初の実装者であるBjarne Stroustrupは、以下のように簡潔にまとめている。 + +> C++は、Simulaのプログラム構造化のための機構と、Cのシステムプログラミング用の効率性と柔軟性を提供するために設計された。C++は半年ほどで現場で使えることを見込んでいた。結果として成功した。 +> +> Bjarne Stroustrup, A Hisotory of C++: 1979-1991, HOPL2 + +プログラミング言語史に詳しくない読者は、Simulaというプログラミング言語について知らないことだろう。Simulaというのは、初めてオブジェクト指向プログラミングを取り入れたプログラミング言語だ。当時と言えばまだ高級なプログラミング言語はほとんどなく、if else, whileなどのIBMの提唱した構造化プログラミングを可能にする文法を提供しているプログラミング言語すら、多くは研究段階であった。いわんやオブジェクト指向など、当時はまだアカデミックにおいて可能性の一つとして研究されている程度の地に足のついていない夢の機能であった。そのような粗野な時代において、Simulaは先進的なオブジェクト指向プログラミングを実現していた。 + +問題は、Simulaの設計と実装では実行速度が遅く、大規模なプログラムを開発するには適さなかった。 + +Cの効率性と柔軟性というのは、要するに実行速度が速いとかメモリ消費量が少ないということだ。なぜCは他の言語に比べて効率と柔軟に優れているのか。これには2つの理由がある。 + +ひとつ、Cのコードは直接ハードウェアがサポートする命令にまでマッピング可能であるということ。現実のハードウェアにはストレージがあり、メモリがあり、キャッシュがあり、レジスターがあり、命令は投機的に並列実行される泥臭い計算機能を提供している。 + +ひとつ、使わない機能のコストを支払う必要がないというゼロオーバーヘッドの原則。例えばあらゆるメモリ利用がGCによって管理されている言語では、たとえメモリをすべて明示的に管理していたとしても、GCのコストを支払わなければならない。実行時にメモリレイアウトを判定して実行時に分岐処理ができる言語では、たとえコンパイル時にメモリレイアウトが決定されていたとしても、実行時にメモリレイアウトを判定して条件分岐するコストを支払わなければならない。 + +C++は、「アセンブリ言語をおいて、C++より下に言語を置かない」と宣言するほど、ハードウェア機能への直接マッピングとゼロオーバーヘッドの原則を重視している。 + +C++の他の特徴としては、委員会方式による国際標準規格を定めていることがある。特定の一個人や一法人が所有する言語は、個人や法人の意思で簡単に仕様が変わってしまう。短期的な利益を追求するために長期的に問題となる変更をしたり、単一の実装が仕様だと言わんばかりの振る舞いをする。特定の個人や法人に所有されていないこと、実装が従うべき標準規格があること、独立した実装が複数あること、言語に利害関係を持つ関係者が議論して投票で変更を可決すること、これがC++が長期に渡って使われてきた理由でもある。 + +委員会方式の規格制定では、下位互換性の破壊は忌避される。なぜならば、既存の動いているコードを壊すということは、それまで存在していた資産の価値を毀損することであり、利害関係を持つ委員が反対するからだ。 + +下位互換性を壊した結果何が起こるかと言うと、単に言語が新旧2つに分断される。Python 2とPython 3がその最たる例だ。 + +C++には今日の最新で高級な言語からみれば古風な制約が数多く残っているが、いずれも理由がある。下位互換性を壊すことができないという理由。効率的な実装方法が存在しないという理由。仮に効率的な実装が存在するにしても、様々な環境で実装可能でなければ規格化はできないという理由。 + +C++には良し悪しがある。Bjarne StroustrupはC++への批判にこう答えている。 + +> 言語には2種類ある。文句を言われる言語と、誰も使わない言語。 + +C++は文句を言われる方の言語だ。 diff --git a/200-cpp.md b/200-cpp.md new file mode 100644 index 0000000..32c390f --- /dev/null +++ b/200-cpp.md @@ -0,0 +1,879 @@ +# Cプリプロセッサー + +CプリプロセッサーはC++がC言語から受け継いだ機能だ。CプリプロセッサーはソースコードをC++としてパースする前に、テキストをトークン単位で変形する処理のことだ。この処理はソースファイルをC++としてパースする前処理として行われる。CプリプロセッサーはC++ではなく別言語として認識すべきで、そもそもプログラミング言語ではなくマクロ言語だ。 + +C++ではCプリプロセッサーが広く使われており、今後もしばらくは使われるだろう。読者がC++で書かれた既存のコードを読む時、Cプリプロセッサーは避けて通れない。Cプリプロセッサーはいずれ廃止したい機能ではあるが、C++は未だに廃止できていない。 + +Cプリプロセッサーはプリプロセッシングディレクティブ(preprocessing directive)を認識し、トークン列を処理する。ディレクティブはソースファイルの文頭に文字`#`から始まり、改行文字で終わる。`#`とディレクティブの間に空白文字を入れてもよい。 + +~~~cpp +#define NOSPACE +# define SPACE +~~~ + +## \#includeディレクティブ + +`#include`は指定したファイルの内容をその場に挿入する。本質的にはコピペだ。C++では`#include`はライブラリを利用するのに使われる。 + +`#include`は以下のいずれかの文法を持つ。 + +~~~c++ +#include <ヘッダーファイルパス> 改行文字 +#include "ヘッダーファイルパス" 改行文字 +~~~ + +`#include`は指定したファイルパスのファイルの内容をその場所に挿入する。このファイルをヘッダーファイルという。`<>`によるファイルパスは、標準ライブラリやシステムのヘッダーファイルを格納したディレクトリーからヘッダーファイルを探す。`""`によるファイルパスは、システム以外のディレクトリーからもヘッダーファイルを探す。例えばカレントディレクトリーなどだ。 + +例えば、以下のようなヘッダーファイル`foo.h`があり、 + +~~~c++ +// foo.h +foo foo foo +~~~ + +以下のようなソースファイル`bar.cpp`がある場合、 + +~~~c++ +// bar.cpp + +#include "foo.h" + +// end bar.cpp +~~~ + +`bar.cpp`をCプリプロセッサーにかけると、以下のようなソースファイルが出力される + +~~~c++ +// bar.cpp + +// foo.h +foo foo foo + +// end bar.h +~~~ + +このソースファイルはC++のソースファイルとしてはエラーとなるが、Cプリプロセッサーは単純にトークン列で分割したテキストファイルとしてソースファイルを処理するため、Cプリプロセッサーとしてはエラーにはならない。 + +冒頭で述べたように、`#include`の本質はコンパイラーによるコピペである。あるテキストファイルの内容をその場に挿入するコピペ機能を提供する。 + +`#include`は、他の言語でモジュール、importなどと呼ばれている機能を簡易的に提供する。C++の標準ライブラリを使うには、``や``や``のようなヘッダーファイルを`#include`する必要がある。 + +~~~c++ +// iostreamライブラリを使う +#include +// stringライブラリを使う +#include + +int main() +{ + // のライブラリ + std::string s("hello") ; + // iostreamのライブラリ + std::cout << s ; +} +~~~ + +すでに述べたように`#include`はファイルの内容をその場に挿入するだけであり、他の言語にあるモジュールのための高級な機能ではない。本書を執筆時点で規格策定中のC++20では、より高級なモジュール機能を追加する予定がある。 + +同じヘッダーファイルを複数回`#include`すると、当然複数回挿入される。 + +以下のような`val.h`を、 + +~~~c++ +// val.h +inline int val ; +~~~ + +以下のように複数回`#include`すると、 + +~~~c++ +#include "val.h" +#include "val.h" +~~~ + +以下のように置換される。 + +~~~c++ +// val.h +inline int val ; +// val.h +inline int val ; +~~~ + +これはvalの定義が重複しているためエラーとなる。 + +しかし、ヘッダーファイルを一度しか`#include`しないようにするのは困難だ。なぜならば、ヘッダーファイルは他のヘッダーファイルから間接的に`#include`されることもあるからだ。 + +~~~c++ +// lib_f.h + +#include "val.h" + +int f() ; +~~~ + +~~~c++ +// lib_g.h + +#include "val.h" + +int g() ; +~~~ + +~~~c++ +// main.cpp + +#include "lib_f.h" +#include "lib_g.h" + +int main() +{ + int result = f() + g() ; +} +~~~ + +この`main.cpp`をCプリプロセッサーにかけると以下のように置換される。 + +~~~c++ +// main.cpp + +// lib_f.h + +// val.h +inline int val ; + +int f() ; + +// lib_g.h + +// val.h +inline int val ; + +int g() ; + + +int main() +{ + int result = f() + g() ; +} +~~~ + +これはvalの定義が重複しているためエラーとなる。 + +この問題に対処するためには、複数回`#include`されると困るヘッダーファイルでは、インクルードガード(include guard)と呼ばれている方法を使う。 + +~~~c++ +// val.h + +#ifdef INCLUDE_GUARD_HEADER_VAL_H +#define INCLUDE_GUARD_HEADER_VAL_H + +inline int val ; + +#endif +~~~ + +このように記述した`val.h`を複数回`#include`しても、最初のifdefのみがコンパイル対象になるため、問題は起こらない。 + +インクルードガードは以下の様式を持つ。 + +~~~c++ +#ifdef 十分にユニークなマクロ名 +#define 十分にユニークなマクロ名 + +// 重複してコンパイルされたくないコードをここに書く + +#endif +~~~ + +`十分にユニークなマクロ名`は全ソースファイル中で衝突しないそのヘッダーに固有のマクロ名を使う。慣習的に推奨される方法としてはすべて大文字を使い、十分に長いマクロ名にすることだ。 + +## \#define + +`#define`はマクロ置換を行う。マクロにはオブジェクト風マクロ(object-like macro)と関数風マクロ(function-like macro)がある。風というのは、マクロはオブジェクトでも関数でもないからだ。ただ、文法上オブジェクトや関数の似ているだけで、実態はトークン列の愚直な置換だ。 + +### オブジェクト風マクロ + +オブジェクト風マクロの文法は以下の通り + +~~~ +#define マクロ名 置換リスト 改行文字 +~~~ + +`#define`以降の行では、マクロ名が置換リストに置き換わる + +~~~c++ +#define ONE 1 +#define ONE_PLUS_ONE ONE + ONE +#define GNU GNU's is NOT UNIX + +ONE +ONE_PLUS_ONE +~~~ + +これをプリプロセスすると以下のソースコードになる。 + +~~~c++ +1 +1 + 1 +~~~ + +マクロ名`ONE`は`1`に置換される。 + +マクロ名`ONE_PLUS_ONE`は`ONE + ONE`に置換される。置換された結果に別のマクロ名があれば、そのマクロ名も置換される。 + +あるマクロ名を置換した結果、そのマクロ名が現れても再帰的に置換されることはない。 + +~~~c++ +#define GNU GNU's NOT UNIX! + +GNU +~~~ + +これは以下のように置換される。 + +~~~c++ +GNU's NOT UNIX! +~~~ + +マクロ名`GNU`を展開するとトークン`GNU'が現れるが、これは置換されたマクロ名と同じなので、再帰的に置換されることはない。 + +### 関数風マクロ + +関数風マクロの文法は以下の通り。 + +~~~ +#define マクロ名( 識別子リスト ) 置換リスト 改行文字 +~~~ + +関数風マクロはあたかも関数のように記述できる。関数風マクロに実引数として渡したトークン列は、置換リスト内で仮引数としての識別子で参照できる。 + +~~~c++ +#define NO_ARGUMENT() No argument +#define ONE_ARGUMENT( ARG ) begin ARG end +#define MAKE_IT_DOUBLE( ARG ) ONE_ARGUMENT( ARG ARG ) + +NO_ARGUMENT() +ONE_ARGUMENT( foo bar ) +MAKE_IT_DOUBLE( foo bar ) +~~~ + +これは以下のように置換される。 + +~~~c++ +No argument +begin foo bar end +begin foo bar foo bar end +~~~ + +複数の引数を取るマクロへの実引数は、カンマで区切られたトークン列を渡す。 + +~~~c++ +#define TWO( A, B ) A B +#define THREE( A, B, C ) C B A + +TWO( 1 2, 3 4 ) +THREE( 1, 2, 3 ) +~~~ + +これは以下のように置換される。 + +~~~c++ +1 2 3 4 +3 2 1 +~~~ + +ただし、括弧で囲まれたトークン列の中にあるカンマは、マクロの実引数の区切りとはみなされない。 + +~~~c++ +#define MACRO( A ) A + +MACRO( (a,b) ) +~~~ + +これは以下のように置換される。 + +~~~ +(a,b) +~~~ + +### `__VA_ARGS__`(可変長引数マクロ) + +`#define`の識別子リストを`...`だけにしたマクロは、可変長引数マクロになる。このときマクロの実引数のトークン列は、置換リストのなかで`__VA_ARGS__`として参照できる。 + +~~~c++ +#define MACRO(...) __VA_ARGS__ + +MACRO( You can write , and ,, or even ,,,, ) +~~~ + +これは以下のように置換される。 + +~~~ +You can write , and ,, or even ,,,, +~~~ + +カンマも含めてすべてのトークン列がそのまま`__VA_ARGS__`で参照できる。 + +可変長引数マクロの識別子リストに仮引数と`...`を書いたマクロの置換リストでは、仮引数の数だけの実引数は仮引数で参照され、残りが`__VA_ARGS__`で参照される。 + +~~~c++ +#define MACRO( X, Y, Z, ... ) X Y Z and __VA_ARGS__ + +MACRO( 1,2,3,4,5,6 ) +~~~ + +これは以下のように置換される + +~~~ +1 2 3 and 4,5,6 +~~~ + +X, Y, Zにそれぞれ1, 2, 3が入り、`__VA_ARGS__`には`4,5,6`が入る。 + +### `__VA_OPT__` + +`__VA_OPT__`は可変長引数マクロで`__VA_ARGS__`にトークン列が渡されたかどうかで置換結果を変えることができる。 + +`__VA_OPT__`は可変引数マクロの置換リストでのみ使える。`__VA_OPT__(content)`は`__VA_ARGS__`にトークンがない場合はトークンなしに置換され、トークンがある場合はトークン列`content`に置換される。 + +~~~c++ +#define MACRO( X, ... ) f( X __VA_OPT__(,) __VA_ARGS__ ) + +MACRO(1) +MACRO(1,2) +~~~ + +これは以下のように置換される。 + +~~~ +f( 1 ) +f( 1, 2 ) +~~~ + +`MACRO(1)`は`X`が`1`になり、`__VA_ARGS__`にはトークンがないので、`__VA_OPT__(,)`は空に置換される。結果として`f(1)`となる。 + +`MACRO(1,2)`は、Xが1になり、`__VA_ARGS__'にはトークン`2`が入るので、`__VA_OPT__(,)`は`,`に置換される。結果として`f(1,2)`となる。 + +`__VA_OPT__`は`__VA_ARGS__`に実引数となるトークン列がなければ空に置換されるので、このようにトークン列の有無によってカンマなどの文法上必須のトークン列の有無を切り替えたい場合に使うことができる。 + +### \#演算子 + +`#`はマクロ実引数を文字列リテラルにする。 + +`#`は関数風マクロの置換リストの中のみで使うことができる。`#`は関数風マクロの仮引数の識別子の直前に書くことができる。`#`が直前に書かれた識別子は、マクロ実引数のトークン列の文字列リテラルになる。 + +~~~c++ +#define STRING( X ) # X + +STRING( hello ) +STRING( hello world ) +~~~ + +これは以下のように置換される。 + +~~~ +"hello" +"hello world" +~~~ + +また、可変長マクロと組み合わせた場合、 + +~~~c++ +#define STRING( ... ) # __VA_ARGS__ + +STRING() +STRING( hello,world ) +~~~ + +以下のように置換される。 + +~~~c++ +"" +"hello,world" +~~~ + +### \#\#演算子 + +`##`はマクロ実引数の結合を行う。 + +`##`は関数風マクロの置換リストの中にしか書けない。`##`は両端にマクロの仮引数の識別子を書かなければならない。`##`は両端の識別子の参照するマクロ実引数のトークン列を結合した置換を行う。 + +~~~c++ +#define CONCAT( A, B ) A ## B + +CONCAT( foo, bar ) +CONCAT( aaa bbb, ccc ddd) +~~~ + +これは以下のように置換される。 + +~~~ +foobar +aaa bbbccc ddd +~~~ + +結合した結果のトークンは更にマクロ置換の対象となる。 + +~~~c++ +#define CONCAT( A, B ) A ## B +#define FOOBAR hello + +CONCAT( FOO, BAR ) +~~~ + +これは以下のように置換される。 + +~~~ +hello +~~~ + +`CONCAT(FOO,BAR)`は`FOOBAR`に置換され、FOOBARという名前のマクロ名があるためにさらに`hello`に置換される。 + +### 複数行の置換リスト + +`#define`ディレクティブの置換リストは複数行に渡って書くことができない。これは文法上の制約によるものだ。`#define`ディレクティブは改行文字で終端される。 + +しかし、関数やクラスを生成するような複雑なマクロは、複数行に分けて書きたい。 + +~~~c++ +#define LIST_NAME2( PREFIX, TYPE ) PREFIX ## TYPE +#define LIST_NAME( TYPE ) LIST_NAME2( list_, TYPE ) + +#define DEFINE_LIST( TYPE ) struct LIST_NAME(TYPE){TYPE value ;LIST_NAME(TYPE) * prev ;LIST_NAME(TYPE) * next ;} ; + +DEFINE_LIST(int) +DEFINE_LIST(double) +~~~ + +この場合、行末にバックスラッシュに続けて改行を書くと、バックスラッシュと改行がプリプロセッサーによって削除される。 + +上の例は以下のように、プリプロセッサーとしては比較的わかりやすく書くことができる。 + +~~~c++ +#define LIST_NAME2( PREFIX, TYPE ) PREFIX ## TYPE +#define LIST_NAME( TYPE ) LIST_NAME2( list_, TYPE ) + +#define DEFINE_LIST( TYPE )\ +struct LIST_NAME(TYPE)\ +{\ + TYPE value ;\ + LIST_NAME(TYPE) * prev ;\ + LIST_NAME(TYPE) * next ;\ +} ; + +DEFINE_LIST(int) +DEFINE_LIST(double) +~~~ + +C++ではテンプレートがあるために、このようなマクロを書く必要はない。 + + +### \#undefディレクティブ + +`#undef`はそれ以前に定義されたマクロを削除する。 + +~~~c++ +#define FOO BAR +FOO +#undef FOO +FOO +~~~ + +これは以下のように置換される。 + +~~~ +BAR +FOO +~~~ + +## 条件付きソースファイル選択 + +`#if`, `#elif`, `#else`, `#endif`, `#ifdef`, `#ifndef`は条件付きのソースファイルの選択(conditinal inclusion)を行う。これは条件付きコンパイルに近い機能を提供する。 + +### プリプロセッサーの定数式 + +プリプロセッサーで使える条件式は、C++の条件式とは比べてだいぶ制限がある。基本的には整数定数式で、`true`, `false`が使える他、`123`, `1+1`, `1 == 1`, `1 < 1`のような式も使える。ただし、識別子はすべてマクロ名として置換できるものは置換され、置換できない識別子は、`true`, `false`以外はキーワードも含めてすべて0に置換される。 + +したがって、プリプロセッサーで以下のように書くと、 + +~~~c++ +#if UNDEFINED +#endif +~~~ + +以下のように書いたものと同じになる。 + +~~~c++ +#if 0 +#endif +~~~ + +プリプロセッサーであるので、C++としてのconstexpr変数やconstexpr関数も使えない。 + +~~~c++ +constexpr int x = 1 ; + +#if x +hello +#endif +~~~ + +これは以下のように置換される。 + +~~~ +constexpr int x = 1 ; +~~~ + +プリプロセッサーはC++の文法と意味を理解しない。単にトークン列として処理する。 + +以下の例はエラーになる。 + +~~~c++ +constexpr int f() { return 1 ; } + +#if f() +#endif +~~~ + +なぜならば、`0()`は整数定数式として合法なコードではないからだ。何度も言うように、プリプロセッサーはC++の文法と意味を理解しない。 + +プリプロセッサーの定数式では、特殊なマクロ風の式を使うことができる。`defined`と`__has_include`だ。 + +`defined`は以下の文法を持つ + +~~~ +defined 識別子 +defined ( 識別子 ) +~~~ + +`defined`は識別子がそれ以前の行で`#define`でマクロとして定義されていて`#undef`で取り消されていない場合`1`になり、それ以外の場合0になる。 + +~~~c++ +// #if 0 +#if defined MACRO +#endif + +#define MACRO + +// #if 1 +#if defined MACRO +#endif + +#undef MACRO + +// #if 0 +#if defined MACRO +#endif +~~~ + +`__has_include`は以下の文法を持つ。 + +~~~c++ +__has_include ( < ヘッダーファイル名 > ) +__has_include ( " ヘッダーファイル名 " ) +__has_include ( 文字列リテラル ) +__has_include ( < マクロ > ) +~~~ + +1番目と2番目は、指定されたヘッダーファイル名がシステムに存在する場合`1`に、そうでない場合0になる。 + +~~~c++ +// の存在を確認してから#includeする +#if __has_include() +# include +#endif + +// "mylibrary.h"の存在を確認してから#includeする +#if __has_include("mylibrary.h") +# include "mylibrary.h" +#endif +~~~ + +3番目と4番目は、1番目と2番目が適用できない場合に初めて考慮される。その場合、まず通常通りにプリプロセッサーのマクロ置換が行われる。 + +~~~c++ +#define STDIO "stdio.h" + +#if __has_include( STDIO ) +#endif + +#define STDLIB stdlib.h + +#if __has_include( ) +#endif +~~~ + +### \#ifディレクティブ + +`#if`ディレクティブは以下の文法を持つ。 + +~~~ +#if 定数式 改行文字 + +#endif +~~~ + +もし定数式がゼロの場合、`#if`と`#endif`で囲まれたトークン列は処理されない。定数式が非ゼロの場合、処理される。 + +~~~c++ +#if 0 +This line will be skipped. +#endif + +#if 1 +This line will be processed. +#endif +~~~ + +これをプリプロセスすると以下のようになる。 + +~~~c++ +This line will be processed. +~~~ + +`#if 0`は処理されないので、`#endif`までのトークン列は消える。 + +### \#elifディレクティブ + +`#elif`ディレクティブは、C++でいう`else if`に相当する。 + +~~~c++ + +#elif 定数式 改行文字 +~~~ + +`#elif`ディレクティブは`#if`ディレクティブと`#endif`ディレクティブの間に複数書くことができる。`#elif`のある`#if`が処理される場合、`#if`から`#elif`の間のトークン列が処理される、`#if`が処理されない場合、`#elif`が`#if`と同じように定数式を評価して処理されるかどうかが判断される。`#elif`が処理される場合、処理されるトークン列は次の`#elif`もしくは`#endif`までの間のトークン列になる。 + +以下の例は、すべてYESのトークンがある行のみ処理される。 + +~~~c++ +#if 1 +YES +#elif 1 +NO +#endif + +#if 0 +NO +#elif 1 +YES +#endif + +#if 0 +NO +#elif 1 +YES +#elif 1 +NO +#endif + +#if 0 +NO +#elif 0 +NO +#elif 1 +YES +#endif +~~~ + +プリプロセスした結果は以下の通り、 + +~~~ +YES +YES +YES +YES +~~~ + +### \#elseディレクティブ + +`#else`ディレクティブはC++でいう`else`に相当する。 + +`#else`ディレクティブは`#if`ディレクティブと`#endif`ディレクティブの間に書くことができる。もし`#if`と`#elif`ディレクティブが処理されない場合で`#else`ディレクティブがある場合、`#else`から`#endif`までのトークン列が処理される。 + +以下の例は、YESのトークンがある行のみ処理される。 + +~~~c++ +#if 1 +YES +#else +NO +#endif + +#if 0 +NO +#else +YES +#endif + +#if 0 +NO +#elif 1 +YES +#else +NO +#endif +~~~ + +### \#ifdef, \#ifndefディレクティブ + +~~~ +#ifdef 識別子 +#ifndef 識別子 +~~~ + +は、それぞれ以下と同じ意味になる。 + +~~~ +#if defined 識別子 +#if !defined 識別子 +~~~ + +例、 + +~~~c++ +#ifdef MACRO +#endif + +// 上と同じ +#if defined MACRO +#endif + + +#ifndef MACRO +#endif + +// 上と同じ +#if !defined MACRO +#endif +~~~ + +## \#lineディレクティブ + +`#line`ディレクティブはディレクティブの次の行の行番号と、ソースファイル名を変更する。これは人間が使うのではなく、ツールによって生成されることを想定した機能だ。 + +以下の文法の`#line`ディレクティブは、`#line`ディレクティブの次の行の行番号をあたかも数値で指定した行番号であるかのように振る舞わせる。 + +~~~ +#line 数値 改行文字 +~~~ + +数値として0もしくは2147483647より大きい数を指定した場合の挙動は未定義となる。 + +以下の例はコンパイルエラーになるが、コンパイルエラーメッセージはあたかも102行目に問題があるかのように表示される。 + +~~~c++ +// 1行目 +// 2行目 +#line 100 // 3行目 +// 100行目 +// 101行目 +ill-formed line // 102行目 +~~~ + +以下の例は999を出力するコードだ。 + +~~~cpp +#include +int main() +{ +#line 999 + std::cout << __LINE__ ; +} +~~~ + +以下の文法の`#line`ディレクティブは、次の行の行番号を数値にした上で、ソースファイル名をソースファイル名にする。 + +~~~cpp +#line 数値 "ソースファイル名" 改行文字 +~~~ + +例、 + +~~~cpp +#line 42 "answer.cpp" +~~~ + +以下の文法の`#line`ディレクティブは、プリプロセッサートークン列をプリプロセスし、上の2つの文法のいずれかに合致させる。 + +~~~cpp +#line プリプロセッサートークン列 改行文字 +~~~ + +例、 + +~~~cpp +#define LINE_NUMBER 123 +#line LINE_NUMBER +~~~ + +## \#errorディレクティブ + +`#error`ディレクティブはコンパイルエラーを引き起こす。 + +~~~ +#error 改行文字 +#error トークン列 改行文字 +~~~ + +`#error`によるコンパイラーのエラーメッセージには`#error`のトークン列を含む。 + +`#error`の利用例としては、`#if`と組み合わせるものがある。以下の例はCHAR_BITが8でなければコンパイルエラーになるソースファイルだ。 + +~~~c++ +#include + +#if CHAR_BIT != 8 +#error CHAR_BIT != 8 implementation is not supported. +#endif +~~~ + +`#if`が処理されなければ、その中にある`#error`も処理されないので、コンパイルエラーにはならない。 + +## \#pragmra + +`#pragmra`ディレクティブは実装依存の処理を行う。`#pragma`はコンパイラー独自の拡張機能を追加する文法として使われている。 + +文法は以下の通り。 + +~~~ +#pragma プリプロセッサートークン列 改行文字 +~~~ + +C++では属性が追加されたために、`#pragma`を使う必要はほとんどなくなっている。 + +## Nullディレクティブ + +`Null`ディレクティブとは何もしないプリプロセッサーディレクティブだ。 + +~~~ +# 改行文字 +~~~ + +つまり、単に`#`とだけ書いた行はエラーにはならない。 + +## 定義済みマクロ名 + +いくつかのマクロ名がプリプロセッサーによって予め定義されている。 + +---------------------------------------------------------------------------- +マクロ名 値 意味 +---- ---- ------------------------------------- +\_\_cplusplus 201703L C++17時点での値\ + 将来の規格で増やされる + +\_\_DATE\_\_ "Mmm dd yyyy" ソースファイルがプリプロセスされた日付 + Mmmは月、ddは日、yyyyは年\ + 月の文字列はasctimeが生成するものと同じ\ + 日が1桁の場合、ddの最初の文字は空白文字 + +\_\_FILE\_\_ 文字列リテラル ソースファイルの名前の文字列リテラル + +\_\_LINE\_\_ 整数リテラル ソースファイルの現在の行番号 + +\_\_STDC\_HOSTED\_\_ 整数リテラル ホスト実装の場合1\ + フリースタンディング実装の場合0 + +\_\_STDCPP\_DEFAULT\_NEW\_ALIGNMENT\_\_ 整数リテラル アライメント +-------------------------------------------------------------------------------- diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..41030a7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,693 @@ +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + + + + + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5b1b556 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ + +all : book + +clean : + rm -f index.html + rm -f bin/sample-code-checker + +test : cpptest texttest + +texttest : *.md + textlint -f unix *.md + +cpptest : test-tool + bin/sample-code-checker *.md + +retest : test-tool + bin/sample-code-checker retest /tmp/sample-code-checker/*.cpp + +test-tool : bin/sample-code-checker + +bin/sample-code-checker : bin/sample-code-checker.cpp + g++ -D _ISOC11_SOURCE -std=c++14 --pedantic-errors -Wall -pthread -O2 -o bin/sample-code-checker bin/sample-code-checker.cpp + +book : docs/index.html + + +docs/index.html : *.md style.css + pandoc -s --toc --toc-depth=6 --mathjax -o $@ -H style.css pandoc_title_block *-*.md + +filter.json : *.md style.css + pandoc -t json -s --toc --toc-depth=6 --mathjax -o $@ -H style.css pandoc_title_block *-*.md + +index.md : *.md + pandoc -s --toc --toc-depth=6 --mathjax -o index.md -H style.css pandoc_title_block *-*.md + +.PHONY : all book clean test test-tool texttest cpptest retest diff --git a/bin/sample-code-checker.cpp b/bin/sample-code-checker.cpp new file mode 100644 index 0000000..05f0411 --- /dev/null +++ b/bin/sample-code-checker.cpp @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +std::string all_std_headers = R"( +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +)" ; + +std::string get_unique_file_name() +{ + static std::atomic value ; + + return std::string("/tmp/sample-code-checker/") + std::to_string(++value) + std::string(".cpp") ; +} + +std::string create_temp_source_file( std::string sample_code ) +{ + auto file_name = get_unique_file_name() ; + std::ofstream file( file_name, std::ios_base::out | std::ios_base::trunc ) ; + + file.write( sample_code.c_str(), sample_code.size() ) ; + return file_name ; + +} + + +bool compile_check_gcc( std::string const & file_name ) +{ + std::string command = std::string("g++ -fsyntax-only -D _ISOC11_SOURCE -std=c++1z --pedantic-errors -Wall -pthread -include /tmp/sample-code-checker/all_std_headers.hpp ") + file_name ; + + int result = system( command.c_str() ) ; + + return result == 0 ; + +} + +bool compile_check_clang( std::string const & file_name ) +{ + std::string command = std::string("clang++ -fsyntax-only -D _ISOC11_SOURCE -std=c++1z -stdlib=libc++ --pedantic-errors -Wall -pthread -include-pch /tmp/sample-code-checker/all_std_headers.hpp.pch ") + file_name ; + + int result = system( command.c_str() ) ; + + return result == 0 ; + +} + + + +bool compile_check( std::string const & file_name ) +{ + return + compile_check_gcc( file_name ) + && + compile_check_clang( file_name ) ; +} + +// check if a given sample code is a well-formed C++ code fragment +void check_sample_code( std::string sample_code ) +{ + + auto file_name = create_temp_source_file( sample_code ) ; + + + bool result = compile_check( file_name ) ; + + + if ( result ) + { + remove( file_name.c_str() ) ; + } + else + { + //throw std::logic_error("compilation failed.") ; + } + +} + +// grep all sample code in a file. +void check_source_file( char const * file_name ) +{ + std::cout << "checking: " << file_name << std::endl ; + + // read the entire text file to the memory + std::ifstream file{ file_name } ; + std::string text{ std::istreambuf_iterator{file}, std::istreambuf_iterator{} } ; + + + // search for each sample code + std::regex pattern{ R"(~~~cpp([^]*?)~~~)" } ; + + std::sregex_iterator iter{ text.cbegin(), text.cend(), pattern } ; + std::sregex_iterator end ; + + std::for_each( iter, end, + []( auto && match_result ) + { + auto && sample_code = match_result[1].str() ; + + check_sample_code( sample_code ) ; + } + ) ; +} + +// prepare compiling by +// creating tmp/sample-code-checker directory +// generate precompiled header file. +bool prepare_compile() +{ + mkdir("/tmp/sample-code-checker", S_IRWXU | S_IRWXG) ; + + { + std::ofstream precompiled_header("/tmp/sample-code-checker/all_std_headers.hpp" ) ; + + precompiled_header.write( all_std_headers.c_str(), all_std_headers.size() ) ; + } + + int r1 = std::system("g++ -D _ISOC11_SOURCE -std=c++1z --pedantic-errors -Wall -pthread -x c++-header -o /tmp/sample-code-checker/all_std_headers.hpp.gch /tmp/sample-code-checker/all_std_headers.hpp") ; + + int r2 = std::system("clang++ -D _ISOC11_SOURCE -std=c++14 --pedantic-errors -Wall -pthread -x c++-header -o /tmp/sample-code-checker/all_std_headers.hpp.pch /tmp/sample-code-checker/all_std_headers.hpp") ; + + return r1 == 0 && r2 == 0 ; +} + + +// compile each file +void retest( char ** argv ) +{ + std::cout << "retest" << std::endl ; + for ( char ** iter = argv + 2 ; + *iter != nullptr ; + ++iter ) + { + bool result = compile_check( std::string( *iter ) ) ; + if ( result ) + { + std::cout << "test pass: " << *iter << std::endl ; + } + } +} + +void test( char ** argv ) +{ + // for each file name in arguments + for ( char ** iter = argv + 1 ; + *iter != nullptr ; + ++iter ) + { + check_source_file( *iter ) ; + } + +} + +int main( int argc, char ** argv ) +{ + + prepare_compile() ; + + if ( std::string("retest").compare(argv[1]) == 0 ) + { + retest( argv ) ; + } + else + { + test( argv ) ; + } + + + +} diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..da11a63 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,656 @@ + + + + + + + + + 江添亮のプログラマーのためのC++入門 + + + + + + + +

+

本書はプログラミング経験者向けのC++入門書である。

+

本書の対象読者は、すでに何らかの実用的なプログラミング言語を習得していることを想定し、プログラミングの初歩的な概念はすべて理解しているものとして説明しない。そのため、本書には、「変数は箱のようなものである」といったような説明は出てこない。ただし、主要な他の言語とC++として特別に注意が必要な差は解説している。

+

Cプリプロセッサー

+

CプリプロセッサーはC++がC言語から受け継いだ機能だ。CプリプロセッサーはソースコードをC++としてパースする前に、テキストをトークン単位で変形する処理のことだ。この処理はソースファイルをC++としてパースする前処理として行われる。CプリプロセッサーはC++ではなく別言語として認識すべきで、そもそもプログラミング言語ではなくマクロ言語だ。

+

C++ではCプリプロセッサーが広く使われており、今後もしばらくは使われるだろう。読者がC++で書かれた既存のコードを読む時、Cプリプロセッサーは避けて通れない。Cプリプロセッサーはいずれ廃止したい機能ではあるが、C++は未だに廃止できていない。

+

Cプリプロセッサーはプリプロセッシングディレクティブ(preprocessing directive)を認識し、トークン列を処理する。ディレクティブはソースファイルの文頭に文字#から始まり、改行文字で終わる。#とディレクティブの間に空白文字を入れてもよい。

+
#define NOSPACE
+#    define SPACE
+

#includeディレクティブ

+

#includeは指定したファイルの内容をその場に挿入する。本質的にはコピペだ。C++では#includeはライブラリを利用するのに使われる。

+

#includeは以下のいずれかの文法を持つ。

+
#include <ヘッダーファイルパス> 改行文字
+#include "ヘッダーファイルパス" 改行文字
+

#includeは指定したファイルパスのファイルの内容をその場所に挿入する。このファイルをヘッダーファイルという。<>によるファイルパスは、標準ライブラリやシステムのヘッダーファイルを格納したディレクトリーからヘッダーファイルを探す。""によるファイルパスは、システム以外のディレクトリーからもヘッダーファイルを探す。例えばカレントディレクトリーなどだ。

+

例えば、以下のようなヘッダーファイルfoo.hがあり、

+
// foo.h
+foo foo foo
+

以下のようなソースファイルbar.cppがある場合、

+
// bar.cpp
+
+#include "foo.h"
+
+// end bar.cpp
+

bar.cppをCプリプロセッサーにかけると、以下のようなソースファイルが出力される

+
// bar.cpp
+
+// foo.h
+foo foo foo
+
+// end bar.h
+

このソースファイルはC++のソースファイルとしてはエラーとなるが、Cプリプロセッサーは単純にトークン列で分割したテキストファイルとしてソースファイルを処理するため、Cプリプロセッサーとしてはエラーにはならない。

+

冒頭で述べたように、#includeの本質はコンパイラーによるコピペである。あるテキストファイルの内容をその場に挿入するコピペ機能を提供する。

+

#includeは、他の言語でモジュール、importなどと呼ばれている機能を簡易的に提供する。C++の標準ライブラリを使うには、<iostream><string><vector>のようなヘッダーファイルを#includeする必要がある。

+
// iostreamライブラリを使う
+#include <iostream>
+// stringライブラリを使う
+#include <string>
+
+int main()
+{
+    // <string>のライブラリ
+    std::string s("hello") ;
+    // iostreamのライブラリ
+    std::cout << s ;
+}
+

すでに述べたように#includeはファイルの内容をその場に挿入するだけであり、他の言語にあるモジュールのための高級な機能ではない。本書を執筆時点で規格策定中のC++20では、より高級なモジュール機能を追加する予定がある。

+

同じヘッダーファイルを複数回#includeすると、当然複数回挿入される。

+

以下のようなval.hを、

+
// val.h
+inline int val ;
+

以下のように複数回#includeすると、

+
#include "val.h"
+#include "val.h"
+

以下のように置換される。

+
// val.h
+inline int val ;
+// val.h
+inline int val ;
+

これはvalの定義が重複しているためエラーとなる。

+

しかし、ヘッダーファイルを一度しか#includeしないようにするのは困難だ。なぜならば、ヘッダーファイルは他のヘッダーファイルから間接的に#includeされることもあるからだ。

+
// lib_f.h
+
+#include "val.h"
+
+int f() ;
+
// lib_g.h
+
+#include "val.h"
+
+int g() ;
+
// main.cpp
+
+#include "lib_f.h"
+#include "lib_g.h"
+
+int main()
+{
+    int result = f() + g() ;
+}
+

このmain.cppをCプリプロセッサーにかけると以下のように置換される。

+
// main.cpp
+
+// lib_f.h
+
+// val.h
+inline int val ;
+
+int f() ;
+
+// lib_g.h
+
+// val.h
+inline int val ;
+
+int g() ;
+
+
+int main()
+{
+    int result = f() + g() ;
+}
+

これはvalの定義が重複しているためエラーとなる。

+

この問題に対処するためには、複数回#includeされると困るヘッダーファイルでは、インクルードガード(include guard)と呼ばれている方法を使う。

+
// val.h
+
+#ifdef INCLUDE_GUARD_HEADER_VAL_H
+#define INCLUDE_GUARD_HEADER_VAL_H
+
+inline int val ;
+
+#endif
+

このように記述したval.hを複数回#includeしても、最初のifdefのみがコンパイル対象になるため、問題は起こらない。

+

インクルードガードは以下の様式を持つ。

+
#ifdef 十分にユニークなマクロ名
+#define 十分にユニークなマクロ名 
+
+// 重複してコンパイルされたくないコードをここに書く
+
+#endif
+

十分にユニークなマクロ名は全ソースファイル中で衝突しないそのヘッダーに固有のマクロ名を使う。慣習的に推奨される方法としてはすべて大文字を使い、十分に長いマクロ名にすることだ。

+

#define

+

#defineはマクロ置換を行う。マクロにはオブジェクト風マクロ(object-like macro)と関数風マクロ(function-like macro)がある。風というのは、マクロはオブジェクトでも関数でもないからだ。ただ、文法上オブジェクトや関数の似ているだけで、実態はトークン列の愚直な置換だ。

+

オブジェクト風マクロ

+

オブジェクト風マクロの文法は以下の通り

+
#define マクロ名 置換リスト 改行文字
+

#define以降の行では、マクロ名が置換リストに置き換わる

+
#define ONE             1
+#define ONE_PLUS_ONE    ONE + ONE
+#define GNU GNU's is NOT UNIX
+
+ONE
+ONE_PLUS_ONE
+

これをプリプロセスすると以下のソースコードになる。

+
1
+1 + 1
+

マクロ名ONE1に置換される。

+

マクロ名ONE_PLUS_ONEONE + ONEに置換される。置換された結果に別のマクロ名があれば、そのマクロ名も置換される。

+

あるマクロ名を置換した結果、そのマクロ名が現れても再帰的に置換されることはない。

+
#define GNU GNU's NOT UNIX!
+
+GNU
+

これは以下のように置換される。

+
GNU's NOT UNIX!
+

マクロ名GNUを展開するとトークン`GNU'が現れるが、これは置換されたマクロ名と同じなので、再帰的に置換されることはない。

+

関数風マクロ

+

関数風マクロの文法は以下の通り。

+
#define マクロ名( 識別子リスト ) 置換リスト 改行文字
+

関数風マクロはあたかも関数のように記述できる。関数風マクロに実引数として渡したトークン列は、置換リスト内で仮引数としての識別子で参照できる。

+
#define NO_ARGUMENT()           No argument
+#define ONE_ARGUMENT( ARG )     begin ARG end
+#define MAKE_IT_DOUBLE( ARG )   ONE_ARGUMENT( ARG ARG )
+
+NO_ARGUMENT()
+ONE_ARGUMENT( foo bar )
+MAKE_IT_DOUBLE( foo bar )
+

これは以下のように置換される。

+
No argument
+begin foo bar end
+begin foo bar foo bar end
+

複数の引数を取るマクロへの実引数は、カンマで区切られたトークン列を渡す。

+
#define TWO( A, B ) A B
+#define THREE( A, B, C ) C B A
+
+TWO( 1 2, 3 4 )
+THREE( 1, 2, 3 )
+

これは以下のように置換される。

+
1 2 3 4
+3 2 1
+

ただし、括弧で囲まれたトークン列の中にあるカンマは、マクロの実引数の区切りとはみなされない。

+
#define MACRO( A ) A
+
+MACRO( (a,b) )
+

これは以下のように置換される。

+
(a,b)
+

__VA_ARGS__(可変長引数マクロ)

+

#defineの識別子リストを...だけにしたマクロは、可変長引数マクロになる。このときマクロの実引数のトークン列は、置換リストのなかで__VA_ARGS__として参照できる。

+
#define MACRO(...) __VA_ARGS__
+
+MACRO( You can write , and ,, or even ,,,, )
+

これは以下のように置換される。

+
You can write , and ,, or even ,,,,
+

カンマも含めてすべてのトークン列がそのまま__VA_ARGS__で参照できる。

+

可変長引数マクロの識別子リストに仮引数と...を書いたマクロの置換リストでは、仮引数の数だけの実引数は仮引数で参照され、残りが__VA_ARGS__で参照される。

+
#define MACRO( X, Y, Z, ... ) X Y Z and __VA_ARGS__
+
+MACRO( 1,2,3,4,5,6 )
+

これは以下のように置換される

+
1 2 3 and 4,5,6
+

X, Y, Zにそれぞれ1, 2, 3が入り、__VA_ARGS__には4,5,6が入る。

+

__VA_OPT__

+

__VA_OPT__は可変長引数マクロで__VA_ARGS__にトークン列が渡されたかどうかで置換結果を変えることができる。

+

__VA_OPT__は可変引数マクロの置換リストでのみ使える。__VA_OPT__(content)__VA_ARGS__にトークンがない場合はトークンなしに置換され、トークンがある場合はトークン列contentに置換される。

+
#define MACRO( X, ... ) f( X __VA_OPT__(,) __VA_ARGS__ )
+
+MACRO(1)
+MACRO(1,2)
+

これは以下のように置換される。

+
f( 1 )
+f( 1, 2 )
+

MACRO(1)X1になり、__VA_ARGS__にはトークンがないので、__VA_OPT__(,)は空に置換される。結果としてf(1)となる。

+

MACRO(1,2)は、Xが1になり、__VA_ARGS__'にはトークン2が入るので、VA_OPT(,),に置換される。結果としてf(1,2)`となる。

+

__VA_OPT____VA_ARGS__に実引数となるトークン列がなければ空に置換されるので、このようにトークン列の有無によってカンマなどの文法上必須のトークン列の有無を切り替えたい場合に使うことができる。

+

#演算子

+

#はマクロ実引数を文字列リテラルにする。

+

#は関数風マクロの置換リストの中のみで使うことができる。#は関数風マクロの仮引数の識別子の直前に書くことができる。#が直前に書かれた識別子は、マクロ実引数のトークン列の文字列リテラルになる。

+
#define STRING( X ) # X
+
+STRING( hello )
+STRING( hello world )
+

これは以下のように置換される。

+
"hello"
+"hello world"
+

また、可変長マクロと組み合わせた場合、

+
#define STRING( ... ) # __VA_ARGS__
+
+STRING()
+STRING( hello,world )
+

以下のように置換される。

+
""
+"hello,world"
+

##演算子

+

##はマクロ実引数の結合を行う。

+

##は関数風マクロの置換リストの中にしか書けない。##は両端にマクロの仮引数の識別子を書かなければならない。##は両端の識別子の参照するマクロ実引数のトークン列を結合した置換を行う。

+
#define CONCAT( A, B ) A ## B
+
+CONCAT( foo, bar )
+CONCAT( aaa bbb, ccc ddd)
+

これは以下のように置換される。

+
foobar
+aaa bbbccc ddd
+

結合した結果のトークンは更にマクロ置換の対象となる。

+
#define CONCAT( A, B ) A ## B
+#define FOOBAR hello
+
+CONCAT( FOO, BAR )
+

これは以下のように置換される。

+
hello
+

CONCAT(FOO,BAR)FOOBARに置換され、FOOBARという名前のマクロ名があるためにさらにhelloに置換される。

+

複数行の置換リスト

+

#defineディレクティブの置換リストは複数行に渡って書くことができない。これは文法上の制約によるものだ。#defineディレクティブは改行文字で終端される。

+

しかし、関数やクラスを生成するような複雑なマクロは、複数行に分けて書きたい。

+
#define LIST_NAME2( PREFIX, TYPE ) PREFIX ## TYPE
+#define LIST_NAME( TYPE ) LIST_NAME2( list_, TYPE )
+
+#define DEFINE_LIST( TYPE ) struct LIST_NAME(TYPE){TYPE value ;LIST_NAME(TYPE) * prev ;LIST_NAME(TYPE) * next ;} ; 
+
+DEFINE_LIST(int)
+DEFINE_LIST(double)
+

この場合、行末にバックスラッシュに続けて改行を書くと、バックスラッシュと改行がプリプロセッサーによって削除される。

+

上の例は以下のように、プリプロセッサーとしては比較的わかりやすく書くことができる。

+
#define LIST_NAME2( PREFIX, TYPE ) PREFIX ## TYPE
+#define LIST_NAME( TYPE ) LIST_NAME2( list_, TYPE )
+
+#define DEFINE_LIST( TYPE )\
+struct LIST_NAME(TYPE)\
+{\
+    TYPE value ;\
+    LIST_NAME(TYPE) * prev ;\
+    LIST_NAME(TYPE) * next ;\
+} ; 
+
+DEFINE_LIST(int)
+DEFINE_LIST(double)
+

C++ではテンプレートがあるために、このようなマクロを書く必要はない。

+

#undefディレクティブ

+

#undefはそれ以前に定義されたマクロを削除する。

+
#define FOO BAR
+FOO
+#undef FOO
+FOO
+

これは以下のように置換される。

+
BAR
+FOO
+

条件付きソースファイル選択

+

#if, #elif, #else, #endif, #ifdef, #ifndefは条件付きのソースファイルの選択(conditinal inclusion)を行う。これは条件付きコンパイルに近い機能を提供する。

+

プリプロセッサーの定数式

+

プリプロセッサーで使える条件式は、C++の条件式とは比べてだいぶ制限がある。基本的には整数定数式で、true, falseが使える他、123, 1+1, 1 == 1, 1 < 1のような式も使える。ただし、識別子はすべてマクロ名として置換できるものは置換され、置換できない識別子は、true, false以外はキーワードも含めてすべて0に置換される。

+

したがって、プリプロセッサーで以下のように書くと、

+
#if UNDEFINED
+#endif
+

以下のように書いたものと同じになる。

+
#if 0
+#endif
+

プリプロセッサーであるので、C++としてのconstexpr変数やconstexpr関数も使えない。

+
constexpr int x = 1 ;
+
+#if x
+hello
+#endif
+

これは以下のように置換される。

+
constexpr int x = 1 ;
+

プリプロセッサーはC++の文法と意味を理解しない。単にトークン列として処理する。

+

以下の例はエラーになる。

+
constexpr int f() { return 1 ; }
+
+#if f()
+#endif
+

なぜならば、0()は整数定数式として合法なコードではないからだ。何度も言うように、プリプロセッサーはC++の文法と意味を理解しない。

+

プリプロセッサーの定数式では、特殊なマクロ風の式を使うことができる。defined__has_includeだ。

+

definedは以下の文法を持つ

+
defined 識別子
+defined ( 識別子 )
+

definedは識別子がそれ以前の行で#defineでマクロとして定義されていて#undefで取り消されていない場合1になり、それ以外の場合0になる。

+
// #if 0
+#if defined MACRO
+#endif
+
+#define MACRO
+
+// #if 1
+#if defined MACRO
+#endif
+
+#undef MACRO
+
+// #if 0
+#if defined MACRO
+#endif
+

__has_includeは以下の文法を持つ。

+
__has_include ( < ヘッダーファイル名 > )
+__has_include ( " ヘッダーファイル名 " )
+__has_include ( 文字列リテラル )
+__has_include ( < マクロ > )
+

1番目と2番目は、指定されたヘッダーファイル名がシステムに存在する場合1に、そうでない場合0になる。

+
// <filesystem>の存在を確認してから#includeする
+#if __has_include(<filesystem>)
+#   include <filesystem>
+#endif
+
+// "mylibrary.h"の存在を確認してから#includeする
+#if __has_include("mylibrary.h")
+#   include "mylibrary.h"
+#endif
+

3番目と4番目は、1番目と2番目が適用できない場合に初めて考慮される。その場合、まず通常通りにプリプロセッサーのマクロ置換が行われる。

+
#define STDIO "stdio.h"
+
+#if __has_include( STDIO )
+#endif
+
+#define STDLIB stdlib.h
+
+#if __has_include( <STDLIB> )
+#endif
+

#ifディレクティブ

+

#ifディレクティブは以下の文法を持つ。

+
#if 定数式 改行文字
+
+#endif
+

もし定数式がゼロの場合、#if#endifで囲まれたトークン列は処理されない。定数式が非ゼロの場合、処理される。

+
#if 0
+This line will be skipped.
+#endif
+
+#if 1
+This line will be processed.
+#endif
+

これをプリプロセスすると以下のようになる。

+
This line will be processed.
+

#if 0は処理されないので、#endifまでのトークン列は消える。

+

#elifディレクティブ

+

#elifディレクティブは、C++でいうelse ifに相当する。

+

+#elif 定数式 改行文字
+

#elifディレクティブは#ifディレクティブと#endifディレクティブの間に複数書くことができる。#elifのある#ifが処理される場合、#ifから#elifの間のトークン列が処理される、#ifが処理されない場合、#elif#ifと同じように定数式を評価して処理されるかどうかが判断される。#elifが処理される場合、処理されるトークン列は次の#elifもしくは#endifまでの間のトークン列になる。

+

以下の例は、すべてYESのトークンがある行のみ処理される。

+
#if 1
+YES
+#elif 1
+NO
+#endif
+
+#if 0
+NO
+#elif 1
+YES
+#endif
+
+#if 0
+NO
+#elif 1
+YES
+#elif 1
+NO
+#endif
+
+#if 0
+NO
+#elif 0
+NO
+#elif 1
+YES
+#endif
+

プリプロセスした結果は以下の通り、

+
YES
+YES
+YES
+YES
+

#elseディレクティブ

+

#elseディレクティブはC++でいうelseに相当する。

+

#elseディレクティブは#ifディレクティブと#endifディレクティブの間に書くことができる。もし#if#elifディレクティブが処理されない場合で#elseディレクティブがある場合、#elseから#endifまでのトークン列が処理される。

+

以下の例は、YESのトークンがある行のみ処理される。

+
#if 1
+YES
+#else
+NO
+#endif
+
+#if 0
+NO
+#else
+YES
+#endif
+
+#if 0
+NO
+#elif 1
+YES
+#else
+NO
+#endif
+

#ifdef, #ifndefディレクティブ

+
#ifdef 識別子
+#ifndef 識別子
+

は、それぞれ以下と同じ意味になる。

+
#if defined 識別子
+#if !defined 識別子
+

例、

+
#ifdef MACRO
+#endif
+
+// 上と同じ
+#if defined MACRO
+#endif
+
+
+#ifndef MACRO
+#endif
+
+// 上と同じ
+#if !defined MACRO
+#endif
+

#lineディレクティブ

+

#lineディレクティブはディレクティブの次の行の行番号と、ソースファイル名を変更する。これは人間が使うのではなく、ツールによって生成されることを想定した機能だ。

+

以下の文法の#lineディレクティブは、#lineディレクティブの次の行の行番号をあたかも数値で指定した行番号であるかのように振る舞わせる。

+
#line 数値 改行文字
+

数値として0もしくは2147483647より大きい数を指定した場合の挙動は未定義となる。

+

以下の例はコンパイルエラーになるが、コンパイルエラーメッセージはあたかも102行目に問題があるかのように表示される。

+
// 1行目
+// 2行目
+#line 100 // 3行目
+// 100行目
+// 101行目
+ill-formed line // 102行目
+

以下の例は999を出力するコードだ。

+
#include <iostream>
+int main()
+{
+#line 999
+    std::cout << __LINE__ ;
+}
+

以下の文法の#lineディレクティブは、次の行の行番号を数値にした上で、ソースファイル名をソースファイル名にする。

+
#line 数値 "ソースファイル名" 改行文字
+

例、

+
#line 42 "answer.cpp"
+

以下の文法の#lineディレクティブは、プリプロセッサートークン列をプリプロセスし、上の2つの文法のいずれかに合致させる。

+
#line プリプロセッサートークン列 改行文字
+

例、

+
#define LINE_NUMBER 123
+#line LINE_NUMBER
+

#errorディレクティブ

+

#errorディレクティブはコンパイルエラーを引き起こす。

+
#error 改行文字
+#error トークン列 改行文字
+

#errorによるコンパイラーのエラーメッセージには#errorのトークン列を含む。

+

#errorの利用例としては、#ifと組み合わせるものがある。以下の例はCHAR_BITが8でなければコンパイルエラーになるソースファイルだ。

+
#include <climits>
+
+#if CHAR_BIT != 8
+#error CHAR_BIT != 8 implementation is not supported.
+#endif
+

#ifが処理されなければ、その中にある#errorも処理されないので、コンパイルエラーにはならない。

+

#pragmra

+

#pragmraディレクティブは実装依存の処理を行う。#pragmaはコンパイラー独自の拡張機能を追加する文法として使われている。

+

文法は以下の通り。

+
#pragma プリプロセッサートークン列 改行文字
+

C++では属性が追加されたために、#pragmaを使う必要はほとんどなくなっている。

+

Nullディレクティブ

+

Nullディレクティブとは何もしないプリプロセッサーディレクティブだ。

+
# 改行文字
+

つまり、単に#とだけ書いた行はエラーにはならない。

+

定義済みマクロ名

+

いくつかのマクロ名がプリプロセッサーによって予め定義されている。

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
マクロ名意味
__cplusplus201703LC++17時点での値
+将来の規格で増やされる
__DATE__"Mmm dd yyyy"ソースファイルがプリプロセスされた日付 Mmmは月、ddは日、yyyyは年
+月の文字列はasctimeが生成するものと同じ
+日が1桁の場合、ddの最初の文字は空白文字
__FILE__文字列リテラルソースファイルの名前の文字列リテラル
__LINE__整数リテラルソースファイルの現在の行番号
__STDC_HOSTED__整数リテラルホスト実装の場合1
+フリースタンディング実装の場合0
__STDCPP_DEFAULT_NEW_ALIGNMENT__整数リテラルアライメント
+ + diff --git a/pandoc_title_block b/pandoc_title_block new file mode 100644 index 0000000..445223f --- /dev/null +++ b/pandoc_title_block @@ -0,0 +1,3 @@ +% 江添亮のプログラマーのためのC++入門 +% 江添 亮 +% 2018-02-27 diff --git a/style.css b/style.css new file mode 100644 index 0000000..c1b049d --- /dev/null +++ b/style.css @@ -0,0 +1,27 @@ +