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の
map
とset
の実装に使用するツリー構造が、選択できるようになりました。 - 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_ptr
とunique_ptr
には、生ポインタを取得するためのget()
メンバ関数がある。optional
は、見ようによってはスマートポインタと見なすこともできる。optional
にget()
メンバ関数を入れるのであれば、スマートポインタのように、ポインタを返すべきではないか。optional
のget()
はスマートポインタのインタフェースではなく、生データ(raw data, base data)を参照するセマンティクスなので、別名としてvalue()
にしよう。
この結論を悪いとは思いませんが、私個人は、optional
、boost::initialized
、std::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_builder
をimmutable_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++のドラフト版がリリースされた
Technical Specificationの状況
C++17の標準ライブラリに入れる予定の機能を、std::expreimental
名前空間で先行してリリースし、使用経験を得るためのTechnical Specificationの状況。
C++14は8月15日まで、各国の投票待ち。
以下のTechnical Specificationを、投票のために提出した。
- Filesystem TS : 最終投票のための準備ができたので、もう少しでリリース。
- 最新のドラフト仕様はN3940
- Parallelism TS
- 最新のドラフト仕様はN3989
- Library Fundamentals TS :
not1
、not2
を汎用化した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_int
とtagged_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)に移行しました。
- https://github.com/boostorg/
- リポジトリからのビルド方法は、egtraさんのブログを参照:「Modularized Boost(GitHubへ移行したリポジトリ)を使用する」
- 「Boostの一部の機能を使いたいだけなのに、全部入れないといけないのはしんどい」というのに応えよう、という活動を始めました。
- コミュニティメンテナンスチーム
- 一人のメンテナにライブラリのメンテナンスを丸投げすると、小さなバグもなかなか直されないことがあって困る、というのがあって、その状況を改善するために、コミュニティメンテナンスチーム(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