acl4の開発ログ #03
ここまでのもくじ
2026.01.01(木) #0
- ずっと悩んでいました。機能的にやりたいことを実現するのは全然難しくないのです。
- でもそれをかっこよく書くことができませんでした。どうやってもドンくさいのです。
- しかし今日になって、やっといい感じに書く方法を見つけました。
func(a, b, .c) → func(a, b, ADot1(c))
int func(int a, double b, .char *c) → int func(int a, double b, ADot1(char *c))
→ つまりドット1つから書き始めると、それはカッコ閉じか、次のコンマまでADot1(...) で囲われた形に置換されます。
..int d, e; → ADot2(int d, e;)
→ ドット2つから書き始めると、セミコロンまでを ADot2(...) で囲われた形に置換されます。
func.(a, b, c) → func(ADotArg1, a, b, c)
→ 関数呼び出しの際にドットを入れておくと、ADotArg1という引数を勝手に追加します。
func(,a,,c) → func(a, c)
→ 関数呼び出しなどで、不要なコンマはすべて自動で削除されます。
- たったこれだけをやってくれる簡易プリプロセッサがあれば、私がやりたくてたまらないことは実現できそうなのです。
2026.01.01(木) #1
- どんなことがしたいのか?
- [1] 目立たない方法でいくつかの引数を追加で渡したい。具体的に何を渡すかは後で考える。→ func.(...)
- [2] デバッグモードの時だけ追加の引数を渡したい。→ func(a, b, .c)
- [3] デバッグモードの時だけ変数を宣言したい。そのたびに #if ~ #endif を使うのはかっこわるい。→..int d, e;
2026.01.07(水) #0
- やりたいことを簡潔にまとめてみます。こんな感じのことをC言語でやりたいのです(ライブラリ整備とプリプロセッサ拡張で)。
void func()
{
Enter;
MyClass1 *a = new_MyClass1.();
MyClass2 *b = new_MyClass2.(1, 2, 3.4);
aやbを使って色々する.
Leave;
}
// ポイント:
// newしたけどdeleteしなくていい. Leave すると関数内でnewしたものはすべてdeleteされるから.
// Leaveのタイミングで消えてほしくないときは、 newx_...を使う.
// [Q] newしたポインタを誤ってreturnとかで返してしまったら?
// [A] デバッグレベルが2以上なら、エラーで止まってくれるので何の心配もない. エラー個所も簡単にわかる.
// [Q] Leaveをやり忘れてreturnしたらどうなるの?
// [A] デバッグレベルが2以上なら、エラーで止まってくれるので何の心配もない. エラー個所も簡単にわかる.
2026.01.08(木) #0
- 昨日くらいから、ライブラリ関数やライブラリマクロを「A」で始めるというルールがダメなんじゃないかと思い始めています。
- Aは目立ちすぎるんです。邪魔なんです。
- しかしだからといって、何のプリフィクスもなく書いてもよいというルールにすると、ユーザ関数の関数名や変数名にぶつかるリスクがあります。そこが悩ましいです。
- 私の一番のショックだった出来事は、macのXcodeでmaxとかminという変数名を使おうとしたらエラーが出たことです(もしかしたらXcodeではなかったかもしれません)。たぶんmaxやminというライブラリ関数か何かがあって、それと衝突したんだと思います。
- そのときに、ライブラリ関数とユーザ関数がぶつからないためのルールは必要だと思いました。そうでないと安心してコードを書けないですし、将来ライブラリをバージョンアップしても大丈夫だという安心は得られません。
- うーん、普通にアンダスコアから始めるというルールにしたらいいのかなあ。それだとコンパイラやシステム提供の関数群と衝突する可能性はありますが、ユーザ関数とはぶつからないですみます。
2026.01.08(木) #1
- 悪くなさそうなアイデアに到達しました。
- まず、acl4に関係するライブラリ関数やマクロはすべてacl4_をつけた形で定義します。
acl4_Enter, acl4_Leave, acl4_Class, ...
- その上でライブラリ側に以下のような記述を含ませます。
#if (!defined(acl4_Version))
#define acl4_Version 1
#endif
#if (acl4_Version >= 1)
#define Enter acl4_Enter
#define Leave acl4_Leave
...
#endif
#if (acl4_Version >= 2)
...
#endif
#if (acl4_Version >= 3)
...
#endif
- こうすれば、ライブラリ関数やマクロをどこまで acl4_ のプリフィクスなしで使うのか決められます。acl4のバージョンが上がって新しい関数などが増えてもユーザ関数とぶつかる心配がありません。ちなみに acl4_Version を 0 にしておけば、すべて acl4_ をつけて使うこともできるわけです。
- 「そういえば、<windows.h>にも_WIN32_WINNTっていうのがあったよなー、そっかー、みんな似たようなことを考えるんだなー」と思ったのですが、これはだいぶ意味が違っていて、アプリが想定するよりも古い<windows.h>が与えられたときに、確実にコンパイルエラーにするためのものらしいです。
2026.01.08(木) #2
- [Q] newがどうだとか言っているけど、それって要するにC++の真似をしたいってこと?それなら素直にC++を使えばいいんじゃないの?
- [A] いや別にnewじゃなくてmallocとオブジェクト初期化の関数呼び出しでもよかったのですが、それをnewって書いたほうが伝わりやすいですよね?
- これからいろいろ他の言語の真似をしていくと思います。C++だけじゃないんです。いろんなところからつまみ食いをするイメージなのです。だから「じゃあC++でいいじゃん」にはならないと思うのです。