記号の早見表

C++ の第 2〜6 章と、第 7〜9 章で MISO のコードを読みながら、記号やキーワードの意味を確かめるための表です。 通読する必要はありません。各行の「詳しい説明」から本文の章へ戻れます。

目次

読み方の基本:宣言か式か

C++ では、同じ記号が宣言(新しい名前を作る文)と式(すでにある名前を使う計算)で別の意味になります。 記号に迷ったら、まずその行が名前を作っているのか、使っているのかを確かめます。

double a = 1.0;
double *p = &a;  // * in a declaration: p is a "pointer to double". & in an expression: address of a
*p = 2.0;        // * in an expression: write 2.0 to what p points to (a)
double &r = a;   // & in a declaration: r is an alias (reference) of a

以下の表では、a・b を double の変数、p を double * 型のポインタ、T をテンプレート引数の型として読みます。

* と & と &&

見かけた形

宣言か式か

意味

詳しい説明

double *p = &a;

宣言

p は double を指すポインタです。double* p と書いても同じです

第 3 章

*p、*p = 5.0;

式

p の指す先の値を読み書きします

第 3 章

a * b

式

掛け算です

第 2 章

double &r = a;

宣言

r は a の別名(参照)です。r への代入は a を変えます

第 3 章

void f(double &x)

宣言(引数)

参照渡しです。関数の中で x を変えると、呼び出し元の変数が変わります

第 3 章

const Config &config

宣言(引数)

読むだけの参照渡しです。コピーせず、変更もしません

第 3 章

&a

式

a のアドレスを取り出します

第 3 章

&T::gm

式

クラス T のメンバ gm を指す式です。MISO では「gm があるか」の検査に使います

第 6 章

x && y

式

論理積(かつ)です。Fortran の .and. です

第 2 章

Array3D(Array3D &&other)

宣言(引数)

右辺値参照です。ムーブ(中身の移し替え)を受け取るときに使います

第 4 章

const double *p

宣言

*p を通した変更を禁止します。p の指す先は切り替えられます

第 3 章

double *const p

宣言

p の指す先の切り替えを禁止します。*p を通した変更はできます

第 3 章

T *data_

宣言(メンバ)

Array3DView などが持つ、配列の先頭を指すポインタです

第 4 章

char **argv

宣言(引数)

ポインタを指すポインタです。main のコマンドライン引数で見かけます

第 3 章

MISO のソースは double *p のように * と & を名前の側に付けて書きます(.clang-format の設定)。 double* p と double *p は同じ意味です。

名前とメンバを指す記号(:: . ->)

見かけた形

意味

詳しい説明

std::cout、miso::mhd::MHD

名前空間の中の名前です。miso::mhd:: は「miso の中の mhd の中」です

第 2 章

backend::Host

名前空間 miso::backend の中の型です。using namespace miso; の後では miso:: を省けます

第 2 章、第 6 章

::sinf(x)

先頭の :: は、名前空間の外(一番外側)の名前を指します

第 2 章

Shape::ndims、std::true_type::value

クラスに属する名前(static なメンバ)です。実体を作らずに使えます

第 4 章、第 6 章

T::gm

テンプレート引数 T のメンバです

第 6 章

grid.i_total、qq.ro(i, j, k)

実体(または参照)のメンバを使います

第 4 章

p->x

ポインタ p の指す先のメンバを使います。(*p).x と同じです

第 4 章

this->config

メンバ関数の中で、自分自身を指すポインタ this からメンバを使います。ふつうは this-> を省きます

第 4 章

括弧(<> [] () {})

見かけた形

意味

詳しい説明

#include <vector>

標準ライブラリなど、決まった場所にあるヘッダを読み込みます

第 1 章、第 2 章

#include "array3d.hpp"

自分のファイルからの相対位置でヘッダを探して読み込みます

第 2 章

a < b、n << 1、std::cout << x

比較、ビットのずらし、出力です

第 2 章

std::vector<double>、Array3D<Real, Backend>

テンプレート引数です。山括弧まで含めて 1 つの型の名前になります

第 6 章

template <typename Real>

後から決める型の名前を宣言します

第 6 章

template <>

完全な特殊化です(すべてのテンプレート引数を決めた定義)

第 6 章

pi<Real>、mpi::data_type<Real>()

変数テンプレート・関数テンプレートに型を指定して使います

第 6 章

static_cast<Real>(x)

x を Real 型に変換します

第 2 章

kernel<<<grid, block>>>(...)

CUDA のカーネルの起動です。C++ の記号ではありません

第 9 章

x[i]、grid.x[i]

配列や std::vector の要素です。0 始まりです

第 2 章、第 7 章

double x[3];、int shape_[3]

宣言の [] は、要素数の決まった配列を作ります

第 3 章

new T[n]、delete[] data_

配列の確保と解放です

第 3 章、第 4 章

T &operator[](int idx)

a[idx] と書けるようにする演算子の定義です

第 4 章

[=]、[&]、MISO_LAMBDA(int i) { ... }

ラムダ式(名前のない関数)の始まりです。[=] は値のコピー、[&] は参照で外の変数を取り込みます

第 7 章

f(x)、square<double>(1.5)

関数の呼び出しです

第 2 章

double f(double x);

宣言の () は引数の並びです

第 2 章

qq.ro(i, j, k)

operator() による、配列の要素の読み書きです。Fortran の ro(i, j, k) に似せた書き方です

第 4 章

T &operator()(int i0, int i1, int i2)

a(i, j, k) と書けるようにする演算子の定義です

第 4 章

Array3D<Real> pr(nx, ny, nz);

宣言の後の () は、コンストラクタに渡す値です

第 4 章

(a + b) * c

計算の順序を決める括弧です

第 2 章

if (...) { ... }、for (...) { ... }

処理のまとまり(ブロック)です。中で宣言した変数は } で寿命が終わります

第 2 章、第 3 章

struct Host {};

クラスの本体です。{} は中身が空であることを表します

第 4 章、第 6 章

int n{3};、Range1D range{0, n};

波括弧による初期化です

第 2 章、第 4 章

backend::Host{}、Backend{}

型の値を初期値なしで作る式です。タグ型を関数に渡すときに使います

第 6 章

: grid(grid), qq(grid)

コンストラクタの初期化子リストです() と { の間に書きます)

第 4 章

<...> と (...) の区別が大切です。Array3D<float> a(4, 4, 4); の float は型の指定、4, 4, 4 はコンストラクタへ渡す値です。

その他の演算子

見かけた形

意味

詳しい説明

a = b

代入です。比較は == です

第 2 章

a == b、a != b

等しい・等しくない(Fortran の ==・/=)

第 2 章

x || y、!x

論理和(または)、否定(Fortran の .or.、.not.)

第 2 章

i % n

整数の割り算の余り(Fortran の mod(i, n))

第 2 章

++i、i++

i を 1 増やします

第 2 章

a += b

a = a + b と同じです。-=、*=、/= もあります

第 2 章

c ? a : b

c が真なら a、偽なら b です

第 2 章

~Array3D()

デストラクタ(後片付けの関数)の名前です

第 4 章

= default、= delete

関数の本体の代わりに書く指定です。コンパイラに用意させる・使えなくする

第 4 章

: public ModelBase<...>

クラスの宣言での : は継承です

第 5 章

プリプロセッサの記号(#)

# で始まる行は、コンパイルの前にプリプロセッサが処理します。C++ の文法とは別の、テキストの置き換えです。

見かけた形

意味

詳しい説明

#include

ファイルの中身をその場所に読み込みます

第 1 章、第 2 章

#pragma once

同じヘッダを 2 回読み込まないようにします

第 2 章

#define NAME 値

NAME を後ろの文字列に置き換えるマクロを定義します

第 2 章

#ifdef USE_CUDA 〜 #else 〜 #endif

マクロが定義されているかで、コンパイルする部分を選びます。Fortran の #ifdef と同じです

第 2 章

#ifdef __CUDACC__

CUDA のコンパイラ(nvcc)でビルドしているときだけ有効な部分です

第 6 章、第 9 章

#undef NAME

マクロの定義を取り消します

第 6 章

行末の \

マクロの定義を次の行へ続けます

第 6 章

マクロの中の ##

前後をつないで 1 つの名前にします(has_##name → has_vx)

第 6 章

マクロの中の #name

引数を文字列にします(#name → "vx")

第 6 章

キーワード

宣言の中の位置によって意味が変わるものを中心にまとめます。

キーワード

見かけた形と意味

詳しい説明

const

const Real gm_ = gm;:値を変えられない変数です

第 2 章

const T &x:読むだけの参照です

第 3 章

const T *p と T *const p:* の左なら指す先、右ならポインタ自身を固定します

第 3 章

int size() const:メンバ変数を変えないメンバ関数です

第 4 章

Array3DView<const Real>:要素を読むだけの View です

第 4 章

constexpr

constexpr int n_fields = 9;:コンパイル時に値が決まる定数です

第 2 章

auto

auto dt = mhd.cfl(d.eos);:初期値から型を決めます。auto &d = derived(); は参照になります

第 2 章、第 3 章

using

using Real = float;:型の別名です

第 2 章

using namespace miso;:名前空間の名前を miso:: なしで使えるようにします

第 2 章

using Source = decltype(d.src);:テンプレートの中で、求めた型に別名を付けます

第 6 章

template

template <typename T> ...:テンプレートの宣言です

第 6 章

template <> ...:完全な特殊化です

第 6 章

x.template as<bool>():この後の名前がテンプレートであることを示す印です

第 6 章

typename

template <typename T>:T が型の名前であることを示します。class と書いても同じです

第 6 章

typename T::value_type:テンプレート引数に属する名前が型であることを示します

第 6 章

inline

ヘッダに定義を置く通常の関数や変数に付けます。速くする指定ではありません

第 2 章、第 6 章

static

クラスの中では、実体によらずクラスに属するメンバです

第 4 章

explicit

コンストラクタによる暗黙の型変換を禁止します

第 4 章

noexcept

関数が例外を外へ出さないことを表します

第 4 章

virtual

実行時に派生クラスの関数を選ぶ仮想関数です。MISO では使っていません

第 5 章

decltype(式)

式を実行せずに、その型を求めます

第 6 章

if constexpr

条件がコンパイル時に決まる分岐です。選ばれない側は組み込まれません

第 6 章

static_assert

条件が偽ならコンパイルエラーにします

第 6 章

nullptr

どこも指していないポインタです

第 3 章

this

メンバ関数の中で、自分自身を指すポインタです。ラムダの中で使うと GPU で問題になります

第 4 章、第 7 章、第 9 章

struct、class

クラスの宣言です。struct は既定で public、class は既定で private です

第 4 章

MISO と CUDA の記号

C++ のキーワードではなく、MISO や CUDA が用意する名前です。

見かけた形

意味

詳しい説明

Real

demo で using Real = float; と決める浮動小数点の型です。ライブラリ側ではテンプレート引数です

第 2 章、第 6 章

Backend、backend::Host、backend::CUDA

計算とメモリの場所を表すタグ型です(miso/include/miso/backend.hpp)

第 6 章

MISO_LAMBDA

ラムダ式の始まりを表すマクロです。CPU のビルドでは [=]、CUDA のビルドでは [=] __host__ __device__ になります(miso/include/miso/execution.hpp)

第 7 章、第 9 章

__host__、__device__

関数を CPU・GPU のどちらから呼べるかの指定です。CPU だけのビルドでは空になります(miso/include/miso/cuda_compat.hpp)

第 9 章

__global__

GPU で動くカーネル関数の指定です

第 9 章

MPI_Comm、MPI_Allreduce など

MPI のライブラリの型と関数です

第 8 章

宣言を読むときの確認順序

長い宣言は、次の順に分けて読みます。

  1. 名前を見つけます。 変数・関数・型のどれを宣言しているかを確かめます。

  2. 型を読みます。 <...> まで含めて 1 つの型です。template <...> が前にあれば、山括弧の中の名前は後から決まる型です。

  3. 値・参照・ポインタを区別します。 名前に & や * が付いているかを見ます。

  4. const の対象を確かめます。 値、指す先、ポインタ自身、メンバ関数のどれかを区別します。

  5. 作り方と寿命を確かめます。 初期値、引数、戻り値がどの実体を使い、いつまで使えるかを追います。

例として、miso/include/miso/mhd_integrator.hpp の宣言を分けて読みます。

template <typename Real, typename Source>
__host__ __device__ inline Real source_vx(const Source &src,
                                          const FieldsView<const Real> &qq,
                                          int i, int j, int k);

部分

読み方

template <typename Real, typename Source>

Real と Source は後から決まる型です

__host__ __device__

CPU からも GPU からも呼べる関数です

inline

ヘッダに置く関数です

Real source_vx(...)

名前は source_vx、戻り値の型は Real です

const Source &src

ソース項の実体を、読むだけの参照で受け取ります

const FieldsView<const Real> &qq

要素を読むだけの View(FieldsView<const Real>)を、読むだけの参照で受け取ります

int i, int j, int k

格子点の添字を値で受け取ります

文法の詳細は、C++17 規格草案 N4659 の 参照の宣言、 const の規則、 テンプレートで確認できます。