Boost 1.56.0がリリースされました

GitHubへの移行とモジュール化

このバージョンから、Boostの開発リポジトリSubversionからGitHubに移行しました。それにともない、GitHub上ではBoostの各ライブラリが、モジュールという単位で分割されるようになりました。モジュールは、関連するライブラリを集めたものや、Boostのいろいろなライブラリで使うベースライブラリをまとめたものです。CoreやWinApiなどのモジュールは後者になります。

新ライブラリ

Boost 1.56.0では、アラインメントを扱うAlignライブラリと、C++11のstd::type_indexのBoost版でもあり、それの拡張も入っているType Indexライブラリが追加されました。

非推奨ライブラリ

BoostからC++11標準に入れるたたき台となっていたライブラリ群であるTR1が非推奨になりました。このライブラリは、Boostの機能をstd::tr1名前空間で定義し直しただけのものなので、Boostの機能を使うか、C++11標準ライブラリを代わりに使ってください。

その他主要な更新

  • boost::variantが可変引数テンプレートに対応しました。コンパイルがいくらか速くなることを期待できます。
  • Containerに、DLmallocベースのアロケータが入りました。
  • Containerのmapsetの実装に使用するツリー構造が、選択できるようになりました。
  • Flyweightが、可変引数テンプレート、ムーブ、initializer_listでの初期化に対応しました。
  • Multi-Indexのhashed_indicesが、高速化しました。
  • Multiprecisionに、2進表現の浮動小数点数cpp_bin_floatが追加されました。
  • Optionalが、C++標準に提案されている仕様に対応しました。ムーブやemplace()のサポート、値にアクセスする新たな方法として、value()value_or()value_or_eval()のサポートが追加されました。(nulloptはまだ)
  • Smart Pointerの、make_shared()allocate_shared()に、配列のサポートが追加されました。
  • Threadに、C++標準のConcurrency TSで提案されているfutureの拡張であるwhen_any()when_all()が追加され、同様に提案されているexecutorが追加されました。

そのほか細かい変更は、リリースノートを参照してください。この記事の先頭に、日本語訳したリリースノートへのリンクを貼ってあります。

getかvalueか

std::optionalが提案された最初の時期、中身のデータを取り出す方法が、間接参照演算子しかありませんでした。そのあと、私が「boost::optionalにはget()メンバ関数があるが、こちらにはない。私はポインタインタフェースよりは、そちらを使いたい。」と提案したところ、get()メンバ関数の代わりに、value()メンバ関数が入りました。

その経緯としてはこういうものです。

  • shared_ptrunique_ptrには、生ポインタを取得するためのget()メンバ関数がある。
  • optionalは、見ようによってはスマートポインタと見なすこともできる。
  • optionalget()メンバ関数を入れるのであれば、スマートポインタのように、ポインタを返すべきではないか。
  • optionalget()はスマートポインタのインタフェースではなく、生データ(raw data, base data)を参照するセマンティクスなので、別名としてvalue()にしよう。

この結論を悪いとは思いませんが、私個人は、optionalboost::initializedstd::chrono::durationのようなラッパー型の、生データを参照するインタフェースを共通化したいと考えるので、私が作るクラスでは、get()メンバ関数に統一をしています。

先日の「チェック付き間接参照の提案 またの名をパターンマッチ」が受け入れられる場合は、生データを参照するインタフェースが共通していたほうがいいでしょうから、そのような話になったら、optionalのインタフェースも見直しになるかもしれません。間接参照演算子を共通インタフェースにはしたくないけどポインタも扱えるようにしたい、というなら、traitsのような中間インタフェースを用意することになるとは思います。

参照

immutable_vectorを作った

初期化時に要素の追加・変更を行い、そのあとに「もう変更しない」ことを明示できる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からムーブできます。

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

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

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

Boost 1.56.0 Beta 1が出ました。

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

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

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

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

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

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

追記 2014/07/14 17:37

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

参照

Technical Specificationの状況

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 : コア言語のワーキンググループで、徹底したレビューを行った。この秋には投票を開始できる見込み。

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

#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にした

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

以下のコミットで、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

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