メモ置き場

メモ置き場です.開発したものや調べたことについて書きます.

[tex: ]

CADDi C++勉強会に参加した

CADDiさんが開催しているC++勉強会に参加してきたので,その覚書.

  • type eraser
  • expression template

についての話.

type eraser

type eraserは,型情報を隠すためのテクニック.
テンプレートを利用して,コーディングする際に型を気にしないで済むようにしたもの.日本語だと型消去とか呼ばれてたりするらしい.

C++17以降の標準ライブラリにはstd::anyがある.以下のように,様々な型のオブジェクトを代入することができる.

#include <iostream>
#include <any>
#include <vector>
#include <algorithm>
#include <string>

int main() {

    std::any a = 1;
    // intのリテラルを代入

    std::cout << std::any_cast<int>(a) << std::endl;
    // 1

    a = std::string("this is string");
    // 文字列を代入
    std::cout << std::any_cast<std::string>(a) << std::endl;

    auto vec = std::vector<int>(10);
    for(std::size_t i=0;i<vec.size();i++) vec.at(i) = i;

    a = vec;

    std::any b = a;
    
    auto v = std::any_cast<std::vector<int>>(b);
    for_each(v.begin(), v.end(), [](auto x){ std::cout << x << " ";});
    return 0;
}

C言語でいうvoid*に相当する.

anyの実装例

型消去テクニックを使って実装する.このテクニックは他で活かせる場面がなかなかない(というか多分ない)とのこと.
大切だと思うのは2点あって,

  • anyクラスのコンストラクタをテンプレートにしておいて,コンストラクタの引数の型からテンプレートの型を推論させるところ
  • anyクラスは値を直接持つのではなく,テンプレートクラスで値をラップして保持する.テンプレートクラスはポリモフィックでanyクラスがうまく保持できるようになっているところ

以下に実装例を示す.

// 基底クラス.
struct any_base {
    virtual ~any_base() {}
};

// anyに渡された値を保持するテンプレートクラス
// any_baseを継承しているので,anyクラスでは基底クラスとしてメンバを定義する
template<class T>
struct any_holder : public any_base {
    any_holder(const T &value) : _value(value) {}
    T _value;
};

// anyクラス
// anyクラスはテンプレートクラスではない
class any {
public:
    template<class T>
    any(const T& value) {
        // コンストラクタ引数からテンプレート引数Tを推論
        // holderクラスに値を渡して保持
        _base = new any_holder<T>(value);
    }

    ~any() {
        delete _base;
    }

    any_base *_base;
};

// anyクラスから値を取り出すキャスト
// 本当はanyの持つクラスとテンプレート引数Tが同じであるかを
// チェックする必要がある
template<class T>
T any_cast(any &a) {
    return static_cast<any_holder<T>*>(a._base)->_value;
};

int main() {
    any a = std::string("aaaa");
    std::cout << any_cast<std::string>(a) << std::endl;

    any b = 1;
    std::cout << any_cast<int>(b) << std::endl;
}

expression template

四則演算などの計算式をテンプレートとして表現し,コンパイル時に展開してもらう,というもの.
式の評価の遅延などに使える,らしい.
かなり駆け足での説明だったので,メモを取る時間がなかったので割愛.
どこかで資料を見つけたらまとめておこう.