Pebble Coding

ソフトウェアエンジニアによるIT技術、数学の備忘録

C++17のstd::optional

C++17のstd::optionalはよいので積極的に使っていきましょう。

std::optional

swiftのoptionalと同じようなことができるようになりました。

#include <string>
#include <optional>

struct Data {
    int x;
    int y;
    Data(int x, int y)
        : x(x)
        , y(y)
    {
    }
};

std::optional<Data> makeData(int x, int y)
{
    if (y == 0) {
        return std::nullopt;
    }
    
    return std::make_optional<Data>(x, y);
}

int main(int argc, const char * argv[]) {
    const auto data = makeData(1000, 1);
    if (data) {
        printf("%d %d\n", data->x, data->y);
    }
    
    return 0;
}

C++ 無名ラムダ式の即時実行

C++無名ラムダ式の即時実行の仕方です。
無名ラムダ式定義し、即時実行しています。
無名ラムダの場合は引数部分を定義する必要はなく、キャプチャする変数の指定だけが必要です。

const std::vector<int> list = { 1, 2, 3 };
const auto sum = [&]() {
    return list[0] + list[1] + list[2];
}();
printf("%d\n", sum);

[&]の部分が全ての変数、ここではlistのみですが、を参照キャプチャすることを表しています。
[&]を[]にすると以下のようにコンパイルエラーとなります。
メッセージを見る限り暗黙的にキャプチャできる場合は省略できそうです。

/Users/pebble8888/develop/a/a/main.cpp:13:16: error: variable 'list' cannot be implicitly captured in a lambda with no capture-default specified
        return list[0] + list[1] + list[2];
               ^
/Users/pebble8888/develop/a/a/main.cpp:11:28: note: 'list' declared here
    const std::vector<int> list = { 1, 2, 3 };
                           ^
/Users/pebble8888/develop/a/a/main.cpp:12:22: note: lambda expression begins here
    const auto sum = []() -> int {
                     ^
/Users/pebble8888/develop/a/a/main.cpp:13:26: error: variable 'list' cannot be implicitly captured in a lambda with no capture-default specified
        return list[0] + list[1] + list[2];
                         ^
/Users/pebble8888/develop/a/a/main.cpp:11:28: note: 'list' declared here
    const std::vector<int> list = { 1, 2, 3 };
                           ^
/Users/pebble8888/develop/a/a/main.cpp:12:22: note: lambda expression begins here
    const auto sum = []() -> int {
                     ^
/Users/pebble8888/develop/a/a/main.cpp:13:36: error: variable 'list' cannot be implicitly captured in a lambda with no capture-default specified
        return list[0] + list[1] + list[2];
                                   ^
/Users/pebble8888/develop/a/a/main.cpp:11:28: note: 'list' declared here
    const std::vector<int> list = { 1, 2, 3 };
                           ^
/Users/pebble8888/develop/a/a/main.cpp:12:22: note: lambda expression begins here
    const auto sum = []() -> int {
                     ^
3 errors generated.

なお、ここではラムダ式の戻り値定義を省略しています。

ラムダ式の即時実行を行うメリットは戻り値の変数をconstにできることです。
このコード以後変更されないことが明確になります。

私がラムダ式を使いたい時はほとんど無名ラムダ式です。
名前付きラムダ式を使いたい場合は関数にした方が見通しが良いので全く使いません。
  

C++14 共有ロック

C++14 で共有ロックというものが実装された。
これは1つのリソースに対して、1つのスレッドが書き込みを行い、2つ以上のスレッドが同時に読み込みを行うケースで用いる。
2つの読み込みスレッドは一つのstd::shard_mutexに対して、lock_shared()(共有ロック)を呼び出すと読み込み中であることを宣言することにより、書き込みスレッドが呼び出すlock()(排他ロック)をブロックすることができる。
2つの読み込みスレッドのlock_shared()同士は互いにブロックすることはない。

書き込みスレッドが1つ、読み込みスレッドが1つの場合は利用することに意味はない。

clang-format をいい感じにvimで使う

.vimrc設定

Bundle `cjuniet/clang-format.vim'
let g:clang_format_style="{BasedOnStyle: Google, IndentWidth: 4, Standard: C++11}"

以上です。依存するvimプラグインもなくいい感じです。
使い方は整形したい範囲を行選択してCTRL-Kを押すだけ。
シンプルイズベスト。
ルールをカスタマイズする場合はg:clang_format_styleを編集すれば良いです。

github.com


Googleスタイルの内容を知りたい場合は以下でダンプできるようです。
$ clang-format -style=google -dump-config > .clang-format

mac環境でclang-formatをインストールするには
$ brew install clang-format
を実行すればよいです。