2010-01-27

C++0x本:そろそろ構想を固めなければならない

ここ数日、いろいろと相談しながら考えていたが、やはり、総合的な解説というのはやめようと思う。

総合的な解説というのは、たとえばポインタなら、宣言と初期化、その他の演算などを、ひとつの章で解説するということである。同時に、関数も、宣言と定義とその他のspecifierまで、一箇所で解説することはしない。

ポインタの使い方とか、関数の書き方なら、すでにいくらでも、本は出ている。車輪の再発明をしても仕方がない。

やはり、言語としてどう定義されているかということを考えた目次にするべきだ。この本は、初心者向けの入門書ではないので、それでもいいだろう。

言語として深く解説するというのは、果たして受け入れられるだろうか。

本を書くにあたって、既存のC++の参考書を、あらかた流し読みしてみた。

たとえばconstなメンバ関数だ。既存のC++の参考書では、たいてい、「メンバ関数はconstにできる。これは、そのメンバ関数が、メンバ変数を変更しないという意味である」などと説明している。これは、表面的には正しい。constを指定したメンバ関数は、実際に、メンバ変数を変更することはできない。しかし、言語的には間違っている。もし私が解説するとしたならば、

そもそも、メンバ関数に指定できるのは、constだけではなく、volatileもある。これらはまとめて、cv-qualiferと呼ばれている。では、何がconstやvolatileなのか。*thisである。

thisの型は、そのクラスのポインタである。

struct Foo
{
    void f()
    {
        typedef decltype(this) type ;
    }
} ;

ここで、typeの型は、Foo *である。

そもそも、なぜ非staticなメンバ関数で、thisが使えるのか。それは、メンバ関数に、見えない引数として、クラスのオブジェクトを渡しているからだ。

class Foo
{
public :
    void f(/* Foo & this_ref */)
    {
    // Foo * this = &this_ref ;
    }

} ;

このコードは、厳密に正しいわけではないが、このようになっていると想像すれば、分かりやすい。メンバ関数にconstをつけるということは、この隠された引数にconstをつけるのと同じ意味である。だからこそ、Overload resolutionの際にも、考慮される。

struct Foo
{
    void f() & ; // #1
    void f() const & ; // #2
    void f() volatile & ; // #3
    void f() const volatile & ; // #4

    void f() && ; // #5
    void f() const && ; // #6
    void f() volatile && ; // #7
    void f() const volatile && ; // #8
} ;

int main()
{
    Foo foo ;
    Foo const c_foo ;
    Foo volatile v_foo ;
    Foo const volatile cv_foo ;

    foo.f() ; // #1 
    c_foo.f() ; // #2
    v_foo.f() ; // #3
    cv_foo.f() ; // #4

    std::move(foo).f() ; // #5
    std::move(c_foo).f() ; // #6
    std::move(v_foo).f() ; // #7
    std::move(cv_foo).f() ; // #8
}

こういう説明が一番わかりやすいと思うのだが、一般大衆は、ただ「メンバ変数が変更できない」という説明だけで、この意味が分かるのだろうか。なぜ、以下のコードがエラーになるのか、分かるのだろうか。

struct Foo
{
    void f() {}
} ;

void f( Foo const & foo )
{
    foo.f() ;//Error
}

これを、「メンバ関数にconstをつけてないから、変更される恐れがあるので呼べない」などという解釈で、納得出来るのだろうか。Overload Resolutionのルールの説明なしに理解できるのだろうか。

3 comments:

Anonymous said...

読みモノとして面白いかどうか、で構成するのはナシですかね?
やはり読んでて退屈なのが一番辛い

リファレンスはリファレンスで節を分けて欲しいです
あれは「読む」ものではないですし

Anonymous said...

面白い読み物でないと読めないような人は対象にしない方がよい(と思います)。

この本がもし完成すれば、C++0xのついて知りたければ読まざるを得ない本になるでしょうから、
日本語的に辛いとかでなければそれでいい(と思います)。

そもそも規格を知りたい人が丁寧に読み込むものであって、単なる読み物ではいかん(と思います)。

繰り返し参照されるものだろうし、
このジャンルで後から出るだろう本からは無視できない(参考文献になり得る)存在であるはずで、
ある意味リファレンスですよ。

# おそらくゼミで輪講するレベル(と勝手に思ってますが)。

江添亮 said...

読み物としての面白さを追求すると、D&Eのようになるかと思います。
D&Eはたしかに面白いのですが、あれはむしろ歴史書です。

読み物として面白いとなると、章などという単位に分けなくても読める、連続した物語か、
あるいは、各章が完全に独立した、話集のような形になってしまいます。

どうしてもこの本は、ある章から別の章への参照が多くなるでしょう。
「機能Xについて知りたければ、X章を参照されたし」とか

もちろん、読みやすく書くのは当然です。
漢字が五つも六つも並ぶような単語を使うのは、どう考えても読みやすいとはいえません。

難しいものです。