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

tomlのパーサを作った

こいついつもTOMLのパーサ書いてんな

C++で使えるheader-onlyなTOMLのパーサを書いた。実はこれは2度目である。何故またそんなことをしたか。順に説明していこう。

最初に書こうと思った一番の理由は、「パーサを書いたことがなかったのでいい経験になると思ったから」だ。他の理由の一つに「既存ライブラリのインターフェースがあまり好みでなかったから」というのがあるが、これは単なる好みの問題だと思うので深く突っ込まない(この好みには一応理由はあるが、労力をつぎ込むには根拠が薄弱すぎる)。

次に、今回書き直した理由は、「C++98のことを忘れてC++11以上のことだけ考えて書けばどうなるか」ということと、「以前の自分の設計とインターフェースに不満がでてきたから」だ。

今回の記事では、使い方の説明をREADMEよりは脱線しつつした後、最後に今回書き直した理由をダラダラと述べようと思う。

github.com

続きを読む

erratum: 前回の記事に関して

前回の記事を書いた2日後くらいに、よく考えると先のコードはまずいのではという気もちになった。今日まで放置していたのは、まず自分が書いていたコードを直すことと、書かなければならない書類をこなすことに集中していたからだ。書類は数日前に草稿を共著者に送りつけた。穴だらけだとわかっているので、そろそろまた仕事が帰ってくるだろうが、今この瞬間は少し落ち着けている。もっと仕事を早くこなせるようにならねばならない。

さて、何がまずいかもしれないかというと、まずstd::vectorは(C++17以前は)要素型Tが完全形であることを要求している。よって、以下のような型はおかしいのではないか。

struct X
{
    std::vector<X> xs;
};

ここで、struct Xの宣言が終わる最後の行まで、Xは完全形ではない。しかしその内部でstd::vector<X>を使っている。ここではまだXは不完全型ではないのか。

ところでこれは動く。X x; x.xs.resize(10);とかしても動く。そもそも気づかずに書いてしまった理由は、手元のいくつかのコンパイラで動いたからというのが大きい(C++erとしてはまだまだ未熟だ)。それに、書いているときはstd::vectorは内部的にはヒープにアロケートした配列へのポインタ、つまりここでX*のようなものを持っているに違いないと思っていたため、動くだろうと考えたのだった。

だが実際には上記のように、std::vectorなどコンテナの要素型は完全型でなければならない。ので上のコードが動いたのは、使ったSTL実装が動くようなものだったからで、つまるところ処理系依存な挙動をしたのだと思われる。ちなみに、C++17では不完全型のstd::vectorが作れるようになる。その代わり、アロケータ型が「アロケータ完全性要求」なるものを満たしている必要があるようだが。

よって、以上のような型を書いてはならず、C++17まで待つか、Boost.containerを使うとよい。これは不完全型をサポートしている。

上記リンクから飛ぶこともできるが、以下の記事で標準ライブラリと不完全型の話がなされている。http://www.drdobbs.com/the-standard-librarian-containers-of-inc/184403814

制限解除union

しばらくブログを書いていなかったが、実際のところペーパーワークに駆られて(現在進行形で駆られている)コードをほぼ書けていない。そのストレスで日曜日に何の関係もないコードをゴリゴリ書いていた。そこでタイトルにあるものを使って、ボンミスで時間を飛ばしてしまった。

(2017年5月18日)以下の記事中に登場する私のコードに誤りがあると思われるので、それに関する記事を書いた。

erratum: 前回の記事に関して - in neuro

続きを読む

typedef typename trait::template something<T>::type type;

あるstructのメンバであるtemplate structをtemplate argumentとして受け取ってその中身をtypedefする、というときの書き方が(もう少し普通な状況でも出てくると思うが調べていない)、この18行目の文法がキモい2017だったので置いておく。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

この書き方は寡聞にしてしらなかった

#include <iostream>
#include <array>

struct X
{
    template<typename T> struct fixed_array;
};

template<> 
struct X::fixed_array<double>
{
    typedef std::array<double, 4> type;
};

template<typename T, typename F>
struct Y
{
    typedef typename F::template fixed_array<T>::type type;//これ
    type container;
};

int main()
{
    typedef Y<double, X>::type type;
    type p{{1.,2.,3.,4.}};
    for(auto&& item : p)
        std::cout << item << std::endl;
    return 0;
}

しかし何度か書いてから見直すと自然に見えてくるのだから不思議だ。

vtkで分子を描画

vtk7.0.0が出たという記事を見た時、といってももう1年も前なのだと今気付いたが、分子のためのクラスがあることを知った。で、以前vtkで分子を表示するために複数個の球体を浮かべようと悪戦苦闘した記憶が思い起こされ、こういうものがあるなら使ってみたいと思った。

VTK 7.0.0 | The Kitware Blog

続きを読む

スコープ内の時間計測

以前、関数の時間計測のために返り値をラップする構造体を作っていたが、これはRAII的に考えて

Logger logger;
/*... codes ...*/
{
    stop_watch<std::chrono::milliseconds> sw("block-name", logger);
    /* do_something */
}

とスコープの先頭で宣言すればスコープ内でかかった時間のログが取れるようにできる。

続きを読む

bobthefishでstring関係のエラーが出た

普段、 fish shell なるシェルを愛用している。Linuxに触れて1年半ほどだが、最初は普通にbashを使っており、1年経つか経たないかの頃、ちょうど別のshellのことを考え始めた頃にどこかでfish shellを知って入れてみたのだったと思う。どこで見たのかは忘れてしまった。

続きを読む