SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C++でプロパティを実現するココロミ

  • X ポスト
  • このエントリーをはてなブックマークに追加

プロパティの実装:今ならこうする(?)

 型Tのプロパティは、

  • get: 引数なしで、Tを返す
  • set: const T&を引数とし、Tを返す

の2つの関数オブジェクトを持ち、それぞれ利用者にあらかじめセットしてもらうことにします。標準C++ライブラリが提供するクラステンプレート: std::function<> を用いて:

  std::function<T()>         get;
  std::function<T(const T&)> set;

をprivateメンバに持たせることにしましょう。std::function<>には、テンプレート引数に与えたシグニチャ(引数と戻り値)が一致するなら 関数ポインタ/ラムダ式/ファンクタ(operator()を持つクラス)を問わずセットでき、呼び出すことができます。

list-05
#include <iostream>
#include <functional>

int global_value;

struct get_functor {
    int operator()() const {
        return global_value;
    }
};

int set_function(const int& value) {
    return global_value = value;
}

int main() {
    std::function<int(const int&)> set;
    std::function<int()>           get;

    // function
    set = &set_function;
    set(123);
    std::cout << global_value << std::endl;

    // lambda
    get = []() { return global_value; };
    std::cout << get() << std::endl;

    // functor
    get = get_functor();
    std::cout << get() << std::endl;

}

 また、thisをキャプチャしたラムダ式を与えることでクラスのメンバにもアクセスできます。

list-06
#include <iostream>
#include <functional>

class foo {
private:
  int member_value;
  int set_member(const int& value) { return member_value = value; }
public:

    // コンストラクタで get/set を設定する
    foo() {
        // thisをキャプチャしたlambda式を与える
        get = [this]()                 { return member_value;      };
        set = [this](const int& value) { return set_member(value); };
    }

    std::function<int()>           get;
    std::function<int(const int&)> set;
};

int main() {
    foo f;
    f.set(123);
    std::cout << f.get() << std::endl;
}

 std::function<>を使えばプロパティを実装できそうです。ほとんどナカミがありませんけど...

list-07
#include <functional>

template<class T>
class property {
public:
    void operator()(const std::function<T()>& getter, const std::function<T(const T&)>& setter) {
        // 一度しかセットできないようにしました
        if ( !get ) get = getter;
        if ( !set ) set = setter;
    }

    T operator()() const         { return get(); }
    T operator()(T const& value) { return set(value); }

    operator T() const           { return get(); }
    T operator=(T const& value)  { return set(value); }

    typedef T value_type;

private:
    std::function<T()>         get;
    std::function<T(const T&)> set;
};

次のページ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7571 2014/01/28 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング