隣接要素を処理するfor_each
稀によく使うので書いた。const
版のみ実装した。
実装:
template <class InputRange, class BinaryFunction> void adjacent_for_each(const InputRange& range, BinaryFunction f) { // for ADL using std::begin; using std::end; auto first = begin(range); auto last = end(range); if (first == last) return; while (std::next(first) != last) { const auto& a = *first; ++first; const auto& b = *first; f(a, b); } }
サンプルコード:
#include <iostream> #include <vector> int main() { const std::vector<int> v = {1, 2, 3}; adjacent_for_each(v, [](int a, int b) { std::cout << a << " : " << b << std::endl; }); }
出力:
1 : 2 2 : 3
参照
shared_ptrをweak_ptrに変換するヘルパ関数
// shand/to_weak.hpp #include <boost/config.hpp> #include <memory> namespace shand { template <class T> std::weak_ptr<T> to_weak(const std::shared_ptr<T>& sp) BOOST_NOEXCEPT { return sp; }
C++14から入った、ラムダ式のキャプチャでの初期化で使用する。
#include <iostream> #include <memory> #include <shand/to_weak.hpp> int main() { std::shared_ptr<int> sp(new int(3)); auto f = [wp = shand::to_weak(sp)] { // これ if (std::shared_ptr<int> sp = wp.lock()) { std::cout << *sp << std::endl; } }; f(); }
出力:
3
正規分布の代わりに区間線形分布を使うのもいいかも
中央値(平均値)から、最小値と最大値に向けて左右対称で線形に出現確率が低くなるようなものには、std::piecewise_linear_distribution
を使うのがよさそう。
std::normal_distribution
は、与えるパラメータが平均値と標準偏差で、「平均値 ± 標準偏差」を超える値も出現するから、その外れ値を望まない場合に、std::piecewise_linear_distribution
で代用できそう。
これは、正規分布がほしい、という状況ではなく、中央値付近の値がほしい、という状況です。
#include <random> #include <array> #include <fstream> int main() { std::random_device seed_gen; std::mt19937 engine(seed_gen()); std::array<double, 3> intervals = {-1.0, 0.0, 1.0}, densities = { 0.0, 1.0, 0.0}; std::piecewise_linear_distribution<double> dist { intervals.begin(), intervals.end(), densities.begin() }; std::ofstream file("dist.tsv"); for (std::size_t n = 0; n < 1000 * 1000; ++n) { double result = dist(engine); file << result << "\n"; } }
参照
GCC 5.0のC++関係機能
https://gcc.gnu.org/gcc-5/changes.html
網羅的ではなく、気になったものだけ抽出して書いています。
C++11、C++14関係の対応状況は、cpprefjpサイトにもほぼ反映しました。
- C++14を全実装
- 変数テンプレート
- 宣言時のメンバ初期化を持つ型の集成体初期化を許可
constexpr
の制限緩和- サイズ付きデアロケーション
-std=c++14
オプションが使えるようになる。旧-std=c++1y
オプションは非推奨。- C++11周りのライブラリサポート改善
std::list
のsize()
メンバ関数が、デフォルトでO(1)
になるstd::deque
とstd::vector<bool>
に、ステートフルアロケータのサポートを追加。- iostreamのクラスに、ムーブと
swap
のサポートを追加。 std::align
とstd::aligned_union
のサポートを追加。is_trivially_*
系の型特性を追加。- IOマニピュレータの
put_time
、hexfloat
、defaultfloat
のサポートを追加。 std::isblank
をジェネリックなロケールで使えるようになった。std::shared_ptr
のアトミック操作をサポート。std::notify_all_at_thread_exit()
系の、スレッド終了時にfuture
を準備完了状態にする機能をサポート。
- C++14ライブラリ
is_final
型特性を実装
- C++14後のLibrary Fundamentals TSの機能を追加。
std::experimental
名前空間で定義される。any
クラス(boost::any
と同じ)apply
関数(タプルを展開して関数実行)sample
関数(コンテナからN個の要素をランダム選択)search
関数(文字列特化した探索アルゴリズム)- 変数テンプレートの型特性をいくつか
not_fn
関数(not1
とnot2
を統合し、改善したもの)
- 新しい警告オプションとして、
-Wsuggest-final-types
が入る。「このクラスにはfinal
を付けたほうがいいよ」とオススメしてくれる。 - 拡張機能として、乱数の分布クラス
logistic_distribution
(ロジスティック分布)とuniform_on_sphere_distribution
(球状の一様分布、Boost.Randomにある)を追加。 - IntelのCilk Plusをフルサポート。並列関係の新しい言語拡張。
- Clangにもある
__has_include
をサポート。ヘッダファイルがあるかどうかを調べられる。
STLのイテレータインタフェース再考
STLのイテレータは、コンテナとアルゴリズムをつなぐ中間インタフェース。STLではそのイテレータ自体のインタフェースとして、ポインタの構文を採用している。
ここではそのポインタの構文を、好んで使いたい構文ではないものとし、演算子ではなく名前のついた関数によるインタフェースで、イテレータを再設計してみる。
コード全体は以下を参照:
新しいイテレータインタフェースによるアルゴリズムの実装
まず、新しいイテレータインタフェースを使用しているところ、すなわちアルゴリズムの中身から見てみる。
namespace my_stl { … template <class Iterator, class F> void for_each(Iterator first, Iterator last, F f) { using traits = my_stl::iterator_traits<Iterator>; // no use raw pointer interface Iterator it = first; while (!traits::equal(it, last)) { f(traits::dereference(it)); it = traits::next(it); } } } // namespace my_stl
ここでは、iterator_traits
というクラスが、イテレータのインタフェースとなっている(標準ライブラリに同名のクラスがあるが、それとは別物)。
このクラスは、以下の静的メンバ関数で、イテレータを操作する:
関数 | 説明 |
---|---|
dereference() |
イテレータが指している要素を間接参照する |
next() |
イテレータをひとつ進める |
equal() |
2つのイテレータを等値比較する |
これらは、STLのイテレータインタフェースとしてはそれぞれ、operator*()
、operator++()
、operator==()
に相当する。
イテレータインタフェースの実装
このイテレータは、これらのメンバ名前による操作を直接サポートするイテレータクラスのみならず、従来のSTLと同様に、ポインタもサポートする。iterator_traits
クラスの実装は以下のようになっている:
namespace my_stl { template <class Iterator> struct iterator_traits { static typename Iterator::reference dereference(Iterator& it) { return it.dereference(); } static Iterator next(const Iterator& it) { return it.next(); } static bool equal(const Iterator& a, const Iterator& b) { return a.equal(b); } }; template <class T> struct iterator_traits<T*> { static T& dereference(T* it) { return *it; } static T* next(T* it) { return ++it; } static bool equal(const T* a, const T* b) { return a == b; } }; } // namespace my_stl
iterator_traits
は、デフォルト実装としてのインタフェースのほかに、ポインタに対する特殊化を行っている。これによって、ポインタもイテレータとして振る舞えるようにしてある。
また、これと同じように、自分が使っているコンテナのイテレータが、デフォルトのインタフェースを持っておらず、ポインタでもない場合は、iterator_traits
クラスを特殊化してアダプトすれば、そのイテレータもまたアルゴリズムに適用可能になる。
今回用意したコンテナクラスは、singly_linked_list
という名前の単方向リンクリスト。このコンテナクラスには、デフォルト実装の、dereference()
、next()
、equal()
というメンバ関数を持つイテレータを持たせている。
ユーザーコード
コンテナとイテレータの実装は簡単なものなので省略して、コンテナと配列(ポインタ)をアルゴリズムに適用できているところを確認する。
#include <iostream> int main() { my_stl::singly_linked_list<int> ls; ls.push_front(3); ls.push_front(2); ls.push_front(1); my_stl::for_each(ls.begin(), ls.end(), [](int& x) { std::cout << x << std::endl; }); int ar[3] = {4, 5, 6}; my_stl::for_each(ar, ar + 3, [](int& x) { std::cout << x << std::endl; }); }
出力:
1 2 3 4 5 6
まとめ
ここでは、STLの「ポインタもイテレータとして振る舞えるようにする」という設計方針を維持したまま、イテレータのインタフェースを見直してみた。近年、データ構造とアルゴリズムをつなぐ中間インタフェースを用意するライブラリが増えてきた。Boost.Graph、Boost.Geometryなどが参考になる。これらのライブラリによって、中間インタフェースの設計がさらに洗練されたので、それを大元であるSTLの設計に適用した、というのが今回の試みだ。
Rangeが出てくると話はまた違ってくるのだが、いまイテレータを再設計するならこうなる、というのを示してみた。
参照
- Iterators Must Go - Andrei Alexandrescu (日本語訳)
- コンセプトを使用しないコンセプト : Traits
- Boost.Geometryに学ぶテンプレートライブラリの設計
- Boost.Graphの設計と最短経路アルゴリズムの使い方いろいろ
- C++テンプレートテクニック 第2版 Chapter 7 コンセプト
書籍『プログラミング言語C++ 第4版』
C++の創始者Bjarne Stroustrupによる『プログラミング言語C++』の第4版、その日本語版が出ます。この版では、C++11への対応が行われています。
SBクリエイティブ社のページはまだないようですが、Amazonでは、2015年1月26日発売になっています。
Emscriptenへのpull requestレポート
Emscriptenにpull requestをして取り込んでもらえたので、そのレポートです。
Emscriptenとは
C言語とC++で書いたコードを、LLVMを使ってJavaScriptにコンパイルするコンパイラです。 標準ライブラリの範囲だけでなく、OpenGLのコードを書くとWebGLに、OpenALやSDLのAPIでオーディオ関係のコードを書くとWeb Audioにコンパイルされたりもします。
pull requestの内容
直した内容としては、たったの1行です。
Emscriptenのドキュメントを眺めていたら、リリースノートへのリンクが切れていたので、正しいリンクに直しました。
詳細なやりとり
最初のpull request。
- 私の修正としては、リンク切れを直して、ChangeLogをChangeLog.markdownのように拡張子を直しただけです。
- その修正に対していろいろなコメントが入りました。
- jujさんから、「AUTHORS(作者たち)に名前を載せるから、AUTHORSに名前を追加するpull requestをください。pull requestの練習だと思ってやってみて。」と言われ、いろいろ調べながらpull requestしたブランチに追加のコミットをした。
- pull request先がmasterブランチになっていたので、「開発ブランチはincomingだからそっちにpull requestし直してほしい」と言われた。
やり直したpull requestが以下:
これを送ったら、10分後くらいにすぐ取り込んでもらえました。
まとめ
Emscriptenでのpull requestでまず感じたのは、開発者を育てる文化があっていいな、ということでした。pull requestにさらに修正を依頼するのはコントリビュートのハードルを上げることになるので、pull requestに多少問題があっても、開発者がマージしてから手直しをする、ということが事例として多いです。しかし、実際に修正を依頼されてやってみて、自分の成長が感じられたのでやってよかったと思います。
また、AUTHORSに名前を載せてもらえたこともうれしかったです。1行コミットしかしていないのに恐縮ですが、Emscriptenはコントリビュータを大事にしていることがわかりました。
もし今後Emscriptenにコントリビュートする方がいたら、何らかの参考になれば幸いです。
C++17の新機能予定
C++17、およびTechnical Speficicationに採択された提案文書。
コア言語
- N4259: Wording for std::uncaught_exceptions (Herb Sutter)
- 捕捉していない例外の数を取得する関数を追加する。
- N4261: Proposed resolution for Core Issue 330: Qualification conversions and pointers to arrays of pointers (Jens Maurer)
- ポインタの配列を、ポインタへのポインタに変換するときに、
const
修飾を許可する。
- ポインタの配列を、ポインタへのポインタに変換するときに、
- N4262: Wording for Forwarding References (Herb Sutter, Bjarne Stroustrup, Gabriel Dos Reis)
- Scott MeyersがUniversal References(普遍参照?)と呼んでいるものを、規格上Forwarding References(転送参照)と呼ぶことにする。
- N4266: Attributes for namespaces and enumerators (Richard Smith)
- 名前空間と列挙体の定義に、属性を付けられるようにする。
- N4267: Adding u8 character literals (Richard Smith)
- N4268: Allow constant evaluation for all non-type template arguments (Richard Smith)
- 非型テンプレート引数の許可する静的演算を、いくつか追加。配列からポインタへの変換、関数ポインタの変換、修飾子の変換、
std::nullptr_t
からヌルポインタへの変換、std::nullptr_t
からヌルメンバポインタへの変換。
- 非型テンプレート引数の許可する静的演算を、いくつか追加。配列からポインタへの変換、関数ポインタの変換、修飾子の変換、
- N4285: Cleanup for exception-specification and throw-expression (Jens Maurer)
- 例外仕様と例外式の文面を整理
- N4295: Folding expressions (Andrew Sutton, Richard Smith)
- 可変引数テンプレートのパラメータパック全体を畳み込む演算を許可(foldのサポート)。たとえば以下のようなもの:
template<typename... Args> bool f(Args... args) { return (true + ... + args); }
ライブラリ
- N4258: Cleaning-up noexcept in the Library (Nicolai Josuttis)
noexcept
の指定を整理
- N4277: TriviallyCopyable reference_wrapper (Agustín Bergé)
reference_wrapper
をTriviallyCopyable
(memcpy
可能)であると規定する- 内部ではポインタを持ってるだけなので。
- N4279: Improved insertion interface for unique-key maps (Thomas Köppe)
- ユニークなmapのインタフェースに、
try_emplace()
とinsert_or_assign()
を追加する。
- ユニークなmapのインタフェースに、
template <class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template <class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template <class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
- N4280: Non-member size() and more (Riccardo Marcangelo)
- コンテナ用の非メンバ関数として、
size()
、empty()
、data()
を追加する。
- コンテナ用の非メンバ関数として、
- N4284: Contiguous Iterators (Jens Maurer)
- メモリが連続していることが保証されるイテレータの分類を追加する。
Parallelism TS
- N4275: Response to National Body comments for C++ Extensions for Parallelism (Hans-J. Boehm)
- 各国からのコメントに対する回答。
- N4276: Transform Reduce, an Additional Algorithm for C++ Extensions for Parallelism(Jared Hoberock)
transform_reduce()
,transform_exclusive_scan()
,transform_inclusive_scan()
を追加する。
Library Fundamentals TS
- N4270: Collected Edits to the Library Fundamentals TS (Alisdair Meredith)
- 文面の修正
- N4288: Strike string_view::clear from the Library Fundamentals TS (Alisdair Meredith)
basic_string_view
からclear()
メンバ関数を削除。
Library Fundamentals TS 2
- N4257: Delimited iterators (Mike Spertus, Nathan Wilson)
- 区切り文字指定で出力するイテレータを追加する。
ostream_joiner
クラス。
- 区切り文字指定で出力するイテレータを追加する。
- N4273: Uniform Container Erasure (Stephan T. Lavavej)
- remove-eraseイディオムをサポートする非メンバ関数を追加する。
- N4282: The World’s Dumbest Smart Pointer (Walter E. Brown)
- 生ポインタをスマートポインタのインタフェースで使える、「世界一バカなスマートポインタ」として、
observer_ptr
を追加する。 - 以前までは
exempt_ptr
(所有権を保持しないポインタ)という名前だったのが、名称変更された。
- 生ポインタをスマートポインタのインタフェースで使える、「世界一バカなスマートポインタ」として、
Transactional Memory TS
- N4272: Working Draft, Technical Specification for C++ Extensions for Transactional Memory (Michael Wong)
- ドラフト仕様。ほぼ空。
- N4265: Transactional Memory Support for C++: Wording (revision 3) (Jens Maurer, et al.)
- 最新仕様と変更履歴はこちら。
その他、承認された変更
- N4230で、入れ子になった名前空間の定義を、
namespace A::B::C {}
と書けるようにする。意味としてはnamespace A { namespace B { namespace C { }}}
を短く書けるようにしただけ。 - N3922で、よく落とし穴になっていた
auto x{y};
の意味を変更し、y
の型を推論するようにした。これまでは驚くことに、x
はinitializer_list
と推論されていた。 - N4086で、トライグラフを 削除する ことにした。
- N4190で、非推奨になっていた機能をC++17の標準ライブラリから 削除する。
auto_ptr
、bind1st
/bind2nd
、ptr_fun
/mem_fun
/mem_fun_ref
、random_shuffle
、その他いくつか。
boostjp/cpprefjpサイトを、GitHub Pagesに移行します
これまで、boostjpとcpprefjpの両サイトはGoogle Sites上で運営を行っていましたが、GitHub Pagesに移行しようと思います。
旧サイト (Google Sites):
新サイト (GitHub Pages):
GitHubリポジトリでMarkdownドキュメントを編集すると、GitHub Pagesのhtmlに即時変換して反映されるようにしてあります。 その運営ツールは、cpprefjpのGitHubリポジトリにあります。用意してくれた id:melpon に感謝です。
移行の詳細は、cpprefjp GitHubリポジトリのアナウンスIssueを参照してください。
また、それに伴い、boostjp Google Groupの運営を終了しました。
今後とも、boostjp、cpprefjpの両サイトをよろしくお願いします。皆さまのコントリビュートをお待ちしております。
C++忘年会 2014 東京
東京のC++忘年会を12/20(土)に行います!