C++関係の話に出てくる言葉で、「読んで字の如し」
とはいかない難解語の簡単な解説を並べてみました。Glossaryというより、
むしろ略語辞典になってしまいました。巷で見かけた単語を並べているだけなので、
実際の所ほとんど使われない略語もあったりするかもしれません。
- ADL (Argument Dependent name Lookup)
-
引数に依存した名前の探索。
Argument Based Lookup, Koenig Lookup とも呼ばれる。
#include <iostream>
#include <string>
...
std::string s;
std::cout << s << std::endl;
// ostream& std::operator<<( ostream&, string& )
// という関数が、using namespace もせず、std:: も
// 頭に付けずに何故か呼び出せている?
引数の型が hogehoge という名前空間内のものであれば、
hogehoge:: とかが付いていなくても、関数を namespace hogehoge
の中まで探しに行きます。上の演算子の例の場合が、
一番その有効性が現れていると思いますが、この方式は、
演算子でない普通の関数にも適用されます。これがArgument Dependent
Name Lookupです。
個人的には、関数の名前空間がわかっているときに引数を自動で探しに行く、
逆ADLみたいなのも欲しいなぁ、と深く考えずに思っているのですが、
それを導入すると色々と破綻するのかもしれません。
- ARM (The Annotated C++ Reference Manual)
-
書籍「The Annotated C++ Reference Manual」のこと。
省電力なCPU。
ANSIやISOによる標準化前のC++言語のバイブルらしいです。未読ゆえ詳細不明。
- C&E (Generative Programming: Methods, Tools, and Applications)
- 書籍「Generative Programming: Methods, Tools, and Applications」のこと。
さまざまなAspect指向、Intentional Programmingなどなど、と言った
様々なプログラミングパラダイムを紹介し、その上で「生成的プログラミング」
という方法を論じている本です。その「生成的プログラミング」
を実現する方法の一つとして、
C++のtemplateでIFやWHILEといった機能を実装して metaprogramming
を行ってみせていました。
著者のCzarnecki氏とEisenecker氏の頭文字をとってこう呼ばれています。
- COW (Copy On Write)
-
例えば文字列オブジェクトのコピーを考えます。
コピーした後書き換えを行わないならば、その後ずっと2つのオブジェクトとも、
同じ文字列を表し続けるはず。それならば、文字列用メモリのコピーはせず、
ポインタだけコピーしてメモリは共有する、という手で
高速化&省メモリ化 を図ることが出来ます。
どちらかに"書き込みが発生した時点で初めてコピーをする"ので、
CopyOnWriteという名前が付いています。
OSのメモリ管理とかの方面でもよく使われる用語。
- CRTP (Curiously Recurring Template Pattern)
-
「不思議に再帰したテンプレート」パターン。
template< class T > class SomeTemplate { ... };
class SomeClass : public SomeTemplate<SomeClass> { ... };
のように、派生元テンプレートに自分自身を渡す形でクラスを定義するイディオム。
色々便利な使い道がある。名前の出所は、James Coplien氏の95年のC++ Report
誌での記事らしいです。便利な使い道についてはOKA氏の"自己言及的なテンプレート" に詳しい。
- D&E (The Design and Evolution of C++)
-
書籍「The Design and Evolution of C++」のこと。
C++の生みの親であるStroustrup氏が、いかにして現在 ...
と言っても10年近く前に出版された本なのでだいぶ昔ですが ...
のC++が作られたかを語っている本らしいです。未読ゆえ詳細不明。
- EBO (Empty Base Optimization)
-
空の基底クラスの最適化。
メンバ変数を一個も持たない、空のクラス、というものが出来ることがあります。
しかし空のクラスであっても、アドレスは一意に決めなくてはならないので、
sizeof( EmptyClass ) は 0 にはなりません。
EmptyClass arr[100];
assert( &arr[0] != &arr[1] ); // アドレスは違ってて欲しい
単独で使う時にはこの無駄は仕方のないところですが、
例えばこの空クラスから他のクラスを派生するときは、EmptyClass の分のサイズは
0 にして、派生クラスのメンバ変数の分だけを確保する、という最適化が可能です。
C++の規格で許されているこの最適化のことを、Empty Base Optimization
と呼びます。
- ET (Expression Template)
-
式テンプレート。
地球外生命体。
一般的なプログラミング言語は、式の値を計算するには、まず部分式を計算して、
その結果を集めて全体を計算する、というステップを踏むようになっています。
例えば a*b+c/d だったら、まず部分式a*bとc/dを計算して、その結果を足す、と。
もちろんこれはC++でもそうなっています。
が、幾つかの理由から、たまには「式をそのまま式の形として」
覚えておくような処理をしたいことがあります。一つは最適化のため、
もう一つは、boost::lambdaの用に本当に式を式としてとっておく必要がある場合。
これを実現する技法の一つが、ETです。
具体的には、演算子をオーバーロードして、a*b+c/d
の結果型を
add< mul< var<T>,var<T> >,
div< var<T>,var<T> > >
みたいにすることで、templateパラメータの階層の中に、
式(expression)の構造を閉じこめます。詳しくは Todd Veldhuizen 氏の "Techniques for
Scientific C++" などを参照のこと。
- ETI (Early Template Instantiation)
-
テンプレートの早すぎるインスタンス化。
templateへの対応が十分でないコンパイラのバグの一つです。
内部クラステンプレートとの間で相互再帰するようなコードを書いたとき、
正しくテンプレートの定義が行われないという現象のこと。詳細、
及びWorkaroundについてはEffective MPL の Item 5.6 参照。
- Koenig Lookup
-
Argument Depended Lookup のこと。
Andrew Koenig
さんが提案したため、この名前で知られるようになったという。
- LSP (Liskov Substitution Principle)
-
リスコフの代入則、あるいはリスコフの置換原理。
全ての下位クラスのオブジェクトは、上位クラスのオブジェクトが期待されている
部分に渡されても正しく動作しなければならない、という規則。
ヘタにクラス階層の設計をするとこの規則に違反したものができあがって、
そうなるとあまり嬉しくない動作をすることが多いので、注意が必要。
Robert C. Martin氏による記事(PDF)に詳しい。
- MC++D (Modern C++ Design)
-
書籍「Modern C++ Design」のこと。
templateを限界まで使い回すための手引きとなる本です。
- MOJO (MOve of Joint Objects)
-
MC++D の著者Andrei Alexandrescu氏による、
引数に使う一時オブジェクトのコピーという無駄を無くすテクニック。
std::auto_ptrに代表されるような "move semantics"
を持つ移動をうまく使って実装されている。詳細は この記事に。なお、旧バージョンは ZUTO (Zero Unnecessary
Temporary Objects) という名前であった。
- MOP (MetaObject Protocol)
-
クラスの"インスタンス"のメンバ変数を書き換えたりメンバ関数を呼んだり、
というのが普通のプログラミングですが、"クラス"そのものを一種のオブジェクト
(metaobject)と見なして、「クラスのメンバ関数一覧を取得する」とか、
クラス名を文字列で与えて、対応するクラスを取得する、
とかそういったプログラミング手法があります。これを実現する枠組みのことを、
MetaObject Protocol と言います。
勿論そんなことは今のC++では出来ませんので、OpenC++
やDynace
などの別の言語が必要になります。が、Serializationであるとか、
コンポーネントの動的なロードであるとかを考えると簡単なMOPが欲しいなぁ、
と思ってしまうことも多く、純粋にC++の話題であっても時々耳にする単語です。
- NRVO (Named Return Value Optimization)
-
名前付き返値の最適化。
RVO のうち特に、最後の return
文での一時オブジェクトだけでなく、名前付きで普通に作った変数を
return する場合の最適化のこと。名前無しのRVOよりも、
実装している処理系は少ないらしい。(?)
- NTP (Named Template Parameter)
-
名前付きテンプレート引数。
時刻合わせプロトコル。
大量にパラメータを指定出来るようなクラステンプレートを作ると、
実際に使うときには、どれをどんな順番で指定しなければならない…
ということをいちいち確かめる必要があって、大変。
template<
class Pointee,
class OwnerShip = RefLink,
class CheckNull = NoCheckNull,
class ThreadModel = SingleThread
> class smart_ptr { ... };
typedef smart_ptr<MyClass,
RefCount,NoNullCheck,MultiThread> myptr;
もちろんそれぞれのパラメータにデフォルト値を指定しておけば、
たいていの場合は最初の一つだけ指定して終わり、で済むので楽です。
が、この場合もデフォルト以外を使いたくなったら大変。そこで、
各パラメータに名前を付けて、順番は適当に指定出来たらいいな、
という気分になります。
typedef smart_ptr< MyClass,
ThreadModel_is<MultiThread>,
OwnerShip_is<RefCount>,
> myptr;
この技法が、Named Template Parameter です。最近の幾つかのライブラリでは、
NTPでパラメータ指定出来るようになっています。
- ODR (One Definition Rule)
-
"定義は一つ"規則。
プログラム中で、一つの関数は同じただ一つの定義しか持ってはいけない。
一つのクラスは同じただ一つの定義しか持ってはいけない、という規則。
ファイル1で
struct X { int x; };
と書いてファイル2で
struct X { char x; };
と書いていたら、構造体Xに関するODR違反になります。
一見物凄く当たり前なんですが、template の(部分)特殊化版を使った
トリッキーなコードだと、人間の気付かぬ間にODR違反に突入する恐れがあるので、
ちょびっと注意が必要です。
- POD (Plain Old Data)
-
古き良き単純なデータ、というか何と言おうか。
詳細な定義は、ISO C++ 規格の 9.4 にてなされていますが、
ぶっちゃけ、ユーザー定義の代入演算子やデストラクタやらを持たない、
memcpyなどでメモリを直にいじってコピーしたりして問題のない
オブジェクトのこと。
struct Person {
char name[256];
int age;
};
が例えばPODです。
- PTS (Partial Template Specialization)
-
テンプレートの部分特殊化、あるいは部分特殊化版。
template<class T> MyTemplate { ... };
template<class T> MyTemplate<T*> { ... };
template<> MyTemplate<void*> { ... };
例えば一番上がテンプレート、一番下がそのExplicit Specializationで、
真ん中がPartial Specializationです。
void*だ!と完全に指定するのでないけれど、まだ自由度は残しつつ、
ポインタについてのみ扱う特殊なバージョン…というわけです。
もちろん、ポインタ型だけでなく色々な Partial Specialization
があります。
- RAII (Resource Acquisition Is Initialization)
-
「リソースの確保 == 初期化」
その名の通り、メモリ確保や、
Windowハンドルであるとかファイル記述子であるとかのリソースの確保は、
オブジェクトの初期化時に行いましょう、という話。そうすることで、
そのリソースはどのオブジェクトが管理するのか?が明確になり、また、
どこでリソースが確保されるか、ということも把握しやすくなるという寸法です。
転じて、std::auto_ptr や std::fstream のように、
「ユーザが明示的にリソース解放をする必要がなく、
デストラクタで自然に解放される」という設計のことを RAII
と呼ぶことが多くなってしまったようですが。
- RTTI (RunTime Type Information)
-
実行時型情報。あるいは、RunType Type Idenitification(実行時型識別)
class B { public: virtual ~B(){} };
class D1 : public B {};
class D2 : public B {};
B* p1 = new D1;
B* p2 = new D2;
cout << typeid(*p1).name() << endl;
cout << typeid(*p2).name() << endl;
継承を使うと、コンパイル時には実際にどのクラスのインスタンスが入るか
決定せず、実行時に動作が決まる、というようなコードが書けます。
この場合に、実行時にオブジェクトが実際にどの型を持っているか、
の情報を得る仕組み(typeid() と dynamic_cast<>)が C++
には備わっています。それが RTTI。
- RVO (Return Value Optimization)
-
返値の最適化。戻り値の最適化。
struct IntPair {
int fst, snd; IntPair(int f,int s):fst(f),snd(s){}
};
IntPair add( IntPair x, IntPair y )
{
return IntPair( x.fst+y.fst, x.snd+y.snd );
}
...
IntPair a, b;
IntPair c = add(a,b);
素直な実装では、上の例の場合、addの中で足し算結果の
IntPair オブジェクトを一旦作って、戻ってきたそれを、
IntPair のコピーコンストラクタに渡すことで、c を初期化します。
C++の規格ではこのような場合、addの最後で一次オブジェクトを作る代わりに、
直接cを初期化してコピーコンストラクタ呼び出しの回数を減らす、
という最適化をすることが許されています。許されているだけで、
必ず実行されるとは限りませんが、とにかくこのような最適化をRVOと言います。
string int2string(int n)
{
string s;
...// ここで n を文字列表現に変えて s に格納。
return s;
}
RVOの別の例。↑
- SFINAE (Substitution Failure Is Not An Error)
-
「置き換え失敗はエラーにあらず」
struct Abc { typedef char t; };
template<typename T> void f(typename T::t *) { cout << "t"; }
template<typename T> void f(...) { cout << "no t"; }
int main()
{
f<int>( 0 );
// 一個目のfを使おうとしてTをintに置き換えると、
// int::t などというおかしな型が出てきてそんなものは
// 存在しないが、これはエラーとしない。で、別のfを
// 探しに行く。結果、"no t" を表示。
f<Abc>( 0 );
// Abc::t という型が存在するので、一個目の f を使用。
// 結果、"t" を表示。
}
…というC++の規則のこと。これを利用して、class と組込型を区別する
template を書くなどの技が存在します。が、SFINAEを正しく実装している
コンパイラは少ないのが残念。しかし、もう少しマシな名前はなかったのだろうか。
- TC++PL (The C++ Programming Language)
-
書籍「プログラミング言語C++」のこと。