文字列連結

char配列、charstd::stringの任意の組み合わせを連結する関数を書きました。メモリ確保を一回だけします。

C++17の畳み込み式で、全体の文字列長を計算しています。

#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

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

Boost 1.67.0がリリースされました。リリースノートはいつものように、翻訳 + 情報補完したものをboostjpサイトで公開しています。

今回の新ライブラリは、契約プログラミングをサポートするContractと、高階関数を使いやすくするHOF (Higher-order functions) です。

今回のアップデートでは、メンテナンスが滞っていたDateTimeの多くのバグが修正されたり、Type Traitsに任意の式が有効か判断するメタ関数が入ったりしています。

Boost.Pythonで生成されるライブラリファイル名が変更されているので注意してください。

1引数コンストラクタ以外に対するexplicit指定

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にしたほうがいいですね。

最近の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のときに、この本にお世話になった人はすごく多かったと思います。新しくなってこの本が長く残ってくれるのは、うれしい限りですね。