immutable_vectorを作った

C++

初期化時に要素の追加・変更を行い、そのあとに「もう変更しない」ことを明示できるvectorを作りました。ムーブがあるので簡単に作れた。

例:

#include <iostream>
#include <shand/immutable_vector.hpp>

int main()
{
    // 要素の追加・変更
    shand::vector_builder<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);

    // もう変更しない
    shand::immutable_vector<int> iv(std::move(v));

    for (int x : iv) {
        std::cout << x << std::endl;
    }
}

使い方としては、以下のようになります。

  • vector_builderを使い、要素の追加・変更をする。
    • これはただのstd::vectorの別名。
  • 追加・変更が終わったら、vector_builderimmutable_vectorにムーブする。
    • immutable_vectorは、mutableなインタフェースを持たないだけのstd::vectorのラッパー。

これらのクラスは、以下のように、ローカル変数でvector_builder、メンバ変数でimmutable_vectorを持つような状況を想定しています。

class X {
    shand::immutable_vector<T> data_;
public:
    void setupData()
    {
        shand::vector_builder<T> builder;
        …
        data_.build(std::move(builder));
    }
};

immutable_vectorコンストラクタのほかに、build()メンバ関数vector_builderからムーブできます。

チェック付き間接参照の提案 またの名をパターンマッチ

C++

ポインタ操作では、以下のように「間接参照可能か(有効な値を指すポインタか)」をチェックしてから間接参照する、というのがよく行われます。

if (p) {
    T x = *p;
}

これを以下のように書けるようにしよう、というのがこの提案。

if (T x : p) {
}

つまり、間接参照ができるなら間接参照をして値を取り出す、までを一つのif文でやってしまおうというものです。

これは、値の判定と取り出すを同時に行う、ミニマムなパターンマッチと見なすことができます。

この機能は、多くの状況で便利に活用できます。

weak_ptrの場合

weak_ptrは、lock()メンバ関数を使用してshared_ptrオブジェクトを取り出します。その際、以下のようなコードを書くことになりますが、

if (shared_ptr<T> sp = wp.lock()) {
    f(*sp);
}

この状況で欲しいのはshared_ptrオブジェクトではなく、それを間接参照した要素ですので、今回提案されている構文を使えば、このようなコードがより簡潔に書けるようになります:

if (T& x : wp.lock()) {
    f(x);
}

while文の場合

有効な値を取り出せる間ループし続ける、という以下のようなコードも、

while (optional<message> m = try_read(i)) {
    process(*m);
}

この提案の構文をwhile文にも適用すれば、以下のように書けるようになります。

while (message m : try_read(i)) {
    process(m);
}

optionalは間接参照の演算子を持っているので、この構文が適用可能です。

この提案の今後

この提案の作者が、Clangで試しに実装してみるようです。今回の提案はだいぶ小さなものですが、非常に有用なものだと感じます。

Boost 1.56.0 Beta 1

C++

Boost 1.56.0 Beta 1が出ました。

日本語リリースノートは、あと2つくらい残ってますが、だいたい訳してあります。

大きな問題がなければ、2週間くらいでリリースされるでしょう。

Effective Modern C++のドラフト版がリリースされた

C++

書籍『Effective C++』のC++11/14対応である『Effective Modern C++』のドラフト版がリリースされました。価格は$43です。

このバージョンは、完成版ではなく、レビュー中のものになります。正式版のリリースは、10月に予定されています。

正式リリース時には、書籍はフルカラーになる予定だそうです。

追記 2014/07/14 17:37

O'ReillyのEarly Releaseで購入した場合、更新がある度にそれを受け取れて、完成版ももらえるそうです。

参照

Technical Specificationの状況

C++

C++17の標準ライブラリに入れる予定の機能を、std::expreimental名前空間で先行してリリースし、使用経験を得るためのTechnical Specificationの状況。

C++14は8月15日まで、各国の投票待ち。

以下のTechnical Specificationを、投票のために提出した。

  • Filesystem TS : 最終投票のための準備ができたので、もう少しでリリース。
    • 最新のドラフト仕様はN3940
  • Parallelism TS
    • 最新のドラフト仕様はN3989
  • Library Fundamentals TS : not1not2を汎用化したnot_fn(N4076)と、optionalの修正(N4078)を承認した。
    • この変更が入る前の、最新のドラフト仕様はN4023

そのほか、

  • Library Fundamentals TS バージョン2が始動した:このTSのバージョン1はこれから各国のコメントを募集するが、それは微調整程度になるので、バージョン2の準備を始める。
  • Networking TSを再始動した:このTSではネットワークバイトオーダーの変換、IPアドレスURIといった小さく基本的な部分から入れていこうとしていたが、Boost.ASIOをベースにした大きな提案を作成する、という方向に変わった。
  • Concurrency TS : executorの改良を進めているが、なかなか合意がとれない状況。なのでexecutorを一旦TSから取り除いた。
  • Concept TS : コア言語のワーキンググループで、徹底したレビューを行った。この秋には投票を開始できる見込み。

どの派生クラスのオブジェクトが代入されているかを調べる

C++
#include <iostream>
#include <typeinfo>

struct Base {
    virtual void member_function() {} // 仮想関数を持たせておく必要がある
};
struct Derived : public Base {};

int main()
{
    Base* p = new Derived();

    if (typeid(*p) == typeid(Base)) {
        std::cout << "Base" << std::endl;
    }
    if (typeid(*p) == typeid(Derived)) {
        std::cout << "Derived" << std::endl;
    }
}

出力:

Derived

tagged_intとtagged_realのコンストラクタをexplicitにした

C++

破壊的変更なので、ブログに載せておきます。

以下のコミットで、tagged_inttagged_realコンストラクタを、explicitに変更しました。

この変更により、これらのクラスを使っていたコードのコンパイルが通らなくなる可能性があります。

この変更をしたのは、以下のようなコードをコンパイルエラーにしたかったからです。

#include <iostream>
#include <shand/strong_typedef/tagged_int.hpp>

struct Tag {};
using integer = shand::tagged_int<int, Tag>;

void f(integer x) {}

int main()
{
    f(3);          // コンパイルエラーになってほしい
//  f(integer(3)); // こう渡してほしい
}

つまり、関数の引数としてリテラルを渡す際に、それがどの用途の数値型なのかを明示してほしかったのです。

Chronoライブラリのdurationも、コンストラクタexplicitになっているので、それに合わせた形になります。

最近のBoost

C++

Boost 1.56.0のリリースまでもう少しかかりそうなので、Boostの近況を書きます。

  • Boostの開発リポジトリが、SubversionからGit(GitHub)に移行しました。
  • 「Boostの一部の機能を使いたいだけなのに、全部入れないといけないのはしんどい」というのに応えよう、という活動を始めました。
    • GitHubでモジュールごとにリポジトリを分けてるのも、その一環。
    • 現在、モジュール間の依存関係を整理中。そのうち何らかの方法で、「自分が使いたいモジュール(とその依存モジュール)だけを持ってくる」というのができるようになるでしょう。(現在もbcpツールを使えばできることはできる)
  • コミュニティメンテナンスチーム
    • 一人のメンテナにライブラリのメンテナンスを丸投げすると、小さなバグもなかなか直されないことがあって困る、というのがあって、その状況を改善するために、コミュニティメンテナンスチーム(CMT)というのが立ち上げられました。
    • https://svn.boost.org/trac/boost/wiki/CommunityMaintenance
    • CMTに合意したライブラリは、メンテナに限らずBoost開発者コミュニティが、バグ修正、ドキュメント修正、機能追加を行えます。
  • Boostへのライブラリリクエストの方法を改善する。

    • 今までの、Boostにライブラリを入れてもらうようリクエスト/レビューする仕組みは、なかなかレビューが始められない/採択されないという問題がありました。
    • それを改善するために、Boost Library Incubatorというのが動き出しています。
    • http://rrsd.com/blincubator.com/
  • Boostを進化させるための新たなガイドライン

    • BoostはC++03とC++11の両対応をしていますが、C++03をサポートしなければならないことが足かせになってきています。その状況を改善するために、これからのライブラリ開発のガイドラインの見直しが行われています。
    • https://svn.boost.org/trac/boost/wiki/BoostEvo
    • 概要としては、Boostは革新的なライブラリを書くことを奨励するので、新しいライブラリは新しい言語機能をどんどん使っていいよ、としていきたい、としています。
  • Boost.Asioの標準化が進められそう。
    • C++標準のNetworking TSでは、ネットワークバイトオーダーの変換、IPアドレスといった小さな機能から入れていこうとしていましたが、先日の会議では、「いいからBoost.Asioを丸ごと入れようよ」という意見が圧倒的だった、とのこと。
    • http://thread.gmane.org/gmane.comp.lib.boost.devel/252494

浮動小数点数のduration型

C++

C++11標準で提供されているdurationエイリアスは整数のみですが、浮動小数点数もそれなりに使うので、エイリアスを用意しました。

「何秒間で処理を行う」というAPIの引数がdoubleになってる場合がけっこう多いです。

namespace shand {

template <class Rep>
using nanoseconds_t = std::chrono::duration<Rep, std::nano>;
using nanoseconds_f = nanoseconds_t<float>;
using nanoseconds_d = nanoseconds_t<double>;
using nanoseconds_ld = nanoseconds_t<long double>;

template <class Rep>
using microseconds_t = std::chrono::duration<Rep, std::micro>;
using microseconds_f = microseconds_t<float>;
using microseconds_d = microseconds_t<double>;
using microseconds_ld = microseconds_t<long double>;

template <class Rep>
using milliseconds_t = std::chrono::duration<Rep, std::milli>;
using milliseconds_f = milliseconds_t<float>;
using milliseconds_d = milliseconds_t<double>;
using milliseconds_ld = milliseconds_t<long double>;

template <class Rep>
using seconds_t = std::chrono::duration<Rep>;
using seconds_f = seconds_t<float>;
using seconds_d = seconds_t<double>;
using seconds_ld = seconds_t<long double>;

template <class Rep>
using minutes_t =  std::chrono::duration<Rep, std::ratio<60>>;
using minutes_f = minutes_t<float>;
using minutes_d = minutes_t<double>;
using minutes_ld = minutes_t<long double>;

template <class Rep>
using hours_t = std::chrono::duration<Rep, std::ratio<3600>>;
using hours_f = hours_t<float>;
using hours_d = hours_t<double>;
using hours_ld = hours_t<long double>;

} // namespace shand

関連

会議でのレビュー資料

C++

今日は、C++標準化委員会(WG21)の会議で、C++14のDISをレビューしていました。C++14に入る機能を、細かいIssueを除いて全体的にレビューし、日本が投票する際のNational Bodyコメントを決めました。

私は、以下の2件をレビューしました。とくに問題はないです。