最近のC++の学び方について発表しました

英語の資料ですが、PFNの社内セミナーで「最近のC++の学び方」をテーマにして発表しました。(このブログではとくに書いてなかったですが、2017年10月からPreferred Networks社に転職しました)

C++17対応の『C++ポケットリファレンス』 第3版

2018年2月15日に、『C++ポケットリファレンス』の第3版が発売となります。

今回の改訂では、C++17 (ISO/IEC 14882:2017) に対応しています。

執筆関係のこと

執筆自体は2017年4月からはじめて、C++17がISOから発行されたらなるべく早く出版できるよう進めていました。

ツールとしては、執筆環境にGitHubのプライベートリポジトリ、細かい相談ごとにGitterを使用していました。

改訂の内容

C++17では大きな機能がいくつか追加されたため、章立てから見直しています。

  • エラーハンドリングの主要機能としてstd::optionalクラスが追加されたことから、例外の章を、エラーハンドリングの章に変更
  • ファイルシステムのライブラリが追加されたことから、入出力の章にその解説を追加。その代わりにロケール関係を削除

C++14までの機能で、重要度が高く、解説されていなかったリファレンスもいくつか追加しています。

その他、C++17関係の機能として、構造化束縛や追加の属性、if文やswitch文での初期化式、ラムダ式での*thisのコピーキャプチャ、std::variantクラス、文字列検索アルゴリズム、並列アルゴリズムなど多くの解説を追加しています。

締め

主要コンパイラであるGCC、Clang、Visual Studioなどの開発速度が早いこともあり、C++17の多くの機能がすでにユーザーが使える状態になっています。 より新しい機能を使いたい方やそれを周りに広めたい方のために、本書を役立てていただければ幸いです。

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

リリースノートはいつものように、日本語訳 + 情報補完したものをboostjpサイトで公開しています。 今回、新ライブラリはBeast (HTTPライブラリ)、CallableTraits (関数呼び出し関係の型特性ライブラリ)、Mpl11 (C++11以降用のMPL) の3つです。

また、大きな変更として、Boost.Asioライブラリで次期標準ネットワークライブラリの仕様策定と合わせたインタフェース変更が多数行われています。とくに、io_serviceクラスがio_contextクラスに名称変更になっています。古いインタフェースは非推奨となりますので、ご注意ください。

C++17がISOから発行されました

C++17がISO/IEC 14882:2017として発行されました。

cpprefjpサイトでのC++17解説は、鋭意製作中です。

静的なメンバ定数を参照するとリンクエラーとなる

クラス内にstatic constexpr Tで宣言した定数を、std::vector::emplace_back()関数とかに渡すと、リンクエラーになる場合があります。

ミニマムなコードとしては、以下のようになります:

struct X {
    static constexpr int x = 3;
};

template <class T>
void f(T&&) {}

int main()
{
    f(X::x); // リンクエラー : X::xの実体が見つからない
}

クラスの静的定数は、宣言だけした場合にコピーはできますが、その変数のポインタや参照をとったりはできません。そのようなことをしたい場合は、どこかの.cpp/.ccといった拡張子のソースファイルで、変数を定義する必要があります。

struct X {
    static constexpr int x = 3;
};

template <class T>
void f(T&&) {}

constexpr int X::x; // この翻訳単位にX::xの実体を置く
int main()
{
    f(X::x); // OK
}

回避策として考えられるのは、以下のようなものです:

  • C++17のインライン変数で定数を定義する (staticメンバ変数は自動的にインラインになる)
  • constexpr変数ではなく、constexpr関数で定数を定義する

参照

書籍 C++ Templates: The Complete Guide, 2nd Edition

書籍『C++ Templates: The Complete Guide』の第2版が発売しました。

初版はC++03でしたが、今回の改訂でC++17対応しています。

この本は、『C++テンプレート完全ガイド』というタイトルで初版が邦訳されています。C++03のときに、この本にお世話になった人はすごく多かったと思います。新しくなってこの本が長く残ってくれるのは、うれしい限りですね。

Boost 1.65.1リリース

Boost 1.65.0に重大なバグが何件かあったため、パッチバージョンアップしたBoost 1.65.1がリリースされました。1.65.0はスキップして1.65.1を使用してください。

1.65.1のリリースノートには、1.65.0の修正内容も含まれます。

Boost 1.65.0リリース

Boost 1.65.0がリリースされました。リリースノートの日本語訳は、いつものようにboostjpサイトで公開しています。

新ライブラリとして、PolyCollectionとStacktraceが追加されています。

標準C++の欠陥解決は、過去のバージョンに遡って適用される

C++17で入る予定の、可変引数でミューテックスを受け取ってスコープを抜けたらロック解除するscoped_lockクラスですが、C++17がDIS (Draft International Standard) の段階になり、仕様の手直しがもうほぼできない段階になってから、引数順の変更が行われました。

この変更は、ドラフト仕様 (Working Draft) としては、さらに次のバージョンのC++20に適用されました (Editor’s Reportを参照) 。しかし、libstdc++、libc++といった標準ライブラリの実装や、cppreferenceサイトなどでは、この変更がC++17に取り込まれたものとして扱っていました。

さらに、cppreferenceサイトでは、「この変更は、過去にリリースされたC++バージョンに遡って適用された」と書いてありました。そんなことが標準ドキュメントのどこに書いてあるのかわからず、また、過去のバージョンに遡って適用される変更がどれなのかわからないと、なにをC++17と言っていいのかわからなくなります。ですので、std-discussionメーリングリストで質問してみました。

この質問への返答を要約すると、以下のような扱いになっていました:

  • 欠陥 (Defect) の解決は、基本的に過去のバージョンに遡って適用される
  • これは、既知の欠陥と解決策がわかっていれば、コンパイラや標準ライブラリの実装はできるだけ早くそれを適用したいから

それと今回の場合、C++17はまだ策定が完了しておらず、その段階で標準ライブラリの全ての実装が、すでにこの変更に対応しています。ですので、今回の変更は少なくともC++17に含まれると考えられます。また、欠陥の修正は、どのバージョンの仕様書に適用されたかだけでなく、修正内容が報告された時期が重要で、実装にはすぐに適用されることがある、ということがわかりました。

インクルードするディレクトリをマクロ定数として持つ

とある事情から「インクルードするディレクトリが長いので何度も書きたくない」という状況になり、インクルードするディレクトリをマクロ定数に持って、インクルードするファイル名と連結してインクルードしたい、ということがありました。

そんなときの対応は、このようになりました:

// BOOST_PP_STRINGIZEと同等
// トークンを文字列化する
#define PP_XSTR(M) #M
#define PP_STR(x) PP_XSTR(x)

// インクルードするディレクトリ。
// 最後が / になってはならない (トークンとして使えない文字、というエラーになる)
#define MY_LIB_PATH aaa/bbb/ccc

// aaa/bbb/ccc/ddd.hをインクルードする
#include PP_STR(MY_LIB_PATH/ddd.h)

int main() {}

https://wandbox.org/permlink/I6jGIJcqLE4RMHFE

参照