読者です 読者をやめる 読者になる 読者になる

const int よりも int const と書こう、という提案

……という提案を、試しにちょっとしてみます。

ポインタ型とconst

C++er の皆さん、次のコードを正しく説明できるでしょうか?

int hoge = 42;
const int * p1 = &hoge;
int const * p2 = &hoge;
int * const p3 = &hoge;

もちろん答えはこうなります:

int hoge = 42;
const int * p1 = &hoge; // p1の指示先を書き換える事はできないが、p1の指示先自体は変更可能
int const * p2 = &hoge; // p1と同じ
int * const p3 = &hoge; // p3の指示先を書き換える事はできるが、p3の指示先自体は変更不能

つまり、const*の前後どちらにあるかで意味が変わってくるわけですね。
この仕様は、知っている人にとっては不思議でも何でもないのですが、知らないと極めて不可解に見えるどころかソースコードをちゃんと日本語に直せません。困った。

と、そんなわけで今回の提案ですよ!

Oh! Japanese!!

試しに、こんなマクロを定義してみましょう。

#define の不変型 const
#define へのポインタ型 *

これを使うと先程のコードは、

const int へのポインタ型 p1 = &hoge; // p1の指示先を書き換える事はできないが、p1の指示先自体は変更可能
int の不変型 へのポインタ型 p2 = &hoge; // p2の指示先を書き換える事はできないが、p2の指示先自体は変更可能
int へのポインタ型 の不変型 p3 = &hoge; // p3の指示先を書き換える事はできるが、p3の指示先自体は変更不能

となり、いずれの場合も*pが書き換え可能かどうか、あるいはpが変更可能かどうかが一目瞭然になりました。
同様に、

#define の最適化抑止型 volatile
#define への参照型 &
#define の一時オブジェクトへの参照型 &&

のようにもできます。これで「ポインタへの参照って*&だっけ? それとも&*だったっけ?」みたいな混乱からもオサラバ! 「ポインタ型への参照型」なんだから* &に決まってます!

なお、mutableconstvolatileとは性質の異なるキーワードなので、必ず先頭に来なくてはなりません。

で、なんでint constがいいの?

そんなわけで最初の提案に戻ります。

既に答えてしまったようなものですが、constvolatile*&&&も、全て「既存の型に後ろから修飾する形で新しい型を作る」事ができるキーワードです。
が、constvolatileは既存の型の直後に来る場合に限り、「既存の型の前から修飾する形で新しい型を作れ」ます。

もちろん、せいぜい「 const 整数へのポインタ」とか「整数への const ポインタ」とか言っていれらるうちはいいのですが、「 const 整数型への const ポインタのポインタの参照」と言われてconst int * const * &とかさらっと出てくるのは相当の手馴れでしょう。
なのでここは、「整数型の不変型へのポインタ型の不変型へのポインタ型への参照型」と呼ぶ事にしましょう。それで、int const * const * &と書きましょう……ほうら誰でも一発でわかる。

でも、本当は

正直、C++らしく、と思うとこんな風に書きたい:

pointer<add_const<int>::type>::type p1 = &hoge; // p1の指示先を書き換える事はできないが、p1の指示先自体は変更可能
add_const<pointer<int>::type>::type p3 = &hoge; // p3の指示先を書き換える事はできるが、p3の指示先自体は変更不能

でも面倒だから普通にconst*使えばいいや。