Boost 1.68.0がリリースされました。
いつものように、リリースノートの日本語訳 + 情報補完したものを、boostjpサイトで公開しています。
Boost 1.68.0がリリースされました。
いつものように、リリースノートの日本語訳 + 情報補完したものを、boostjpサイトで公開しています。
char
配列、char
、std::string
の任意の組み合わせを連結する関数を書きました。メモリ確保を一回だけします。
#include <string> #include <cstring> #include <utility> std::size_t string_length(const std::string& s) noexcept { return s.size(); } std::size_t string_length(const char* s) noexcept { return std::strlen(s); } std::size_t string_length(char) noexcept { return 1; } template <class... Strings> std::string concat_string(Strings&&... strs) { std::string result; std::size_t length = (string_length(strs) + ...); result.reserve(length); ((result += std::move(strs)), ...); return result; } #include <iostream> int main() { std::string result = concat_string("Hello", ' ', std::string("World")); std::cout << result << std::endl; }
出力:
Hello World
C++03では、ひとつの引数をとるコンストラクタで変換コンストラクタ以外に対してはexplicit
を付ける、という慣習がありました (別の言い方をすると、パラメータ付き構築にexplicit
を付ける)。
C++11では、波カッコ構文による「一様初期化 (Uniform Initialization)」と初期化子リストがあるので、少し事情が異なります。C++11では、explicit
を付けたコンストラクタは、X x = {a, b, c};
のような代入演算子を伴うリスト初期化が禁止されます。
struct X { X(int, int) {} }; struct Y { explicit Y(int, int) {} }; int main() { X x {1, 2}; // OK Y y {1, 2}; // OK X x2 = {1, 2}; // OK // Y y2 = {1, 2}; // error }
そのため、1引数をとるコンストラクタにデフォルト引数をつけてデフォルトコンストラクタと実装をいっしょにすると、意図と違った挙動になる可能性があります。X x = {a, b, c};
構文を許可するかも含めて、任意のコンストラクタにexplicit
を付けるかどうかを検討しましょう。
struct A { A(int=0) {} }; struct B { explicit B(int=0) {} }; int main() { A a{}; // OK B b{}; // OK A a2 = {}; // OK // B b2 = {}; // error }
例として、string(int pos, int len)
みたいなコンストラクタは、explicit
にしたほうがいいですね。
英語の資料ですが、PFNの社内セミナーで「最近のC++の学び方」をテーマにして発表しました。(このブログではとくに書いてなかったですが、2017年10月からPreferred Networks社に転職しました)
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の多くの機能がすでにユーザーが使える状態になっています。 より新しい機能を使いたい方やそれを周りに広めたい方のために、本書を役立てていただければ幸いです。
クラス内に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++ Templates: The Complete Guide』の第2版が発売しました。
初版はC++03でしたが、今回の改訂でC++17対応しています。
この本は、『C++テンプレート完全ガイド』というタイトルで初版が邦訳されています。C++03のときに、この本にお世話になった人はすごく多かったと思います。新しくなってこの本が長く残ってくれるのは、うれしい限りですね。