Rustを触っている

先週Rustを触っていた。まだ手に馴染んでいないので少し不自由さを感じるが、慣れるまでの辛抱だろう。実際は去年くらいに一度インストールしてチュートリアル程度は済ませていたのだが、説明を見て言われた通りのコードを書く以上のことはしていなかった。なので、少し柔軟体操程度のことをしてみるか、とProject Eulerの問題をいくつか解いてみた。これは触ってみただけのひどく個人的な感想にすぎず、Rustの紹介を気合を入れてしている訳ではない。

続きを読む

C++98でもvariantを(バリバリ)使いたい! その2

前回こういう記事が発生した。

c++98でもvariantを(バリバリ)使いたい! その1 - in neuro

このときは単に2つの関数をくっつけて即席visitorを作れるようにして終わったものの、variantは普通2つ以上詰め込むことが多いので、N個版をゴリゴリ展開していく必要に駆られている。

そもそもなんでこんなことになったのかというと、C++98にはvariadic templateがなく、またラムダもないからだ。

状況説明終わり。

続きを読む

c++98でもvariantを(バリバリ)使いたい! その1

私はC++98を使っているプロジェクトに参加している。タイトルを見て「2017年にもなってC++98だとォ〜〜」というような感想を抱くかもしれないが、ライブラリとしてC++98をサポートしたいとか、C++98時代から作っているプログラムでメジャーバージョンアップのタイミングでもないのに切り替えるのはちょっと、とか、共用サーバーにいつまで経ってもC++11対応のコンパイラが入らず泣く泣くg++4.2とかを使わされている(野良ビルドしろよ、というのを全ユーザーに強いるのは酷だと思うのだ)などの理由でC++98はまだまだ現役である。いいか悪いかは別として。

続きを読む

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;
}

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