C++14 でアクセッサを書いてみた

書いてみた。

[ソース]

#include <utility>
#include <iostream>


template<typename T, typename Member>
auto
setter(T t, Member member){
    return [=](auto&& x){
        t ->* member = x;
    };
}

template<typename T, typename Member>
auto
getter(T t, Member member){
    return [=]{
        return t ->* member;
    };
}


class X{
    int value = 42;
public:
    decltype(setter(std::declval<X*>(), &X::value)) set_value = setter(this, &X::value);
    decltype(getter(std::declval<X*>(), &X::value)) get_value = getter(this, &X::value);
    // auto 使いたい
//  auto set_value = setter(this, &X::value);
//  auto get_value = getter(this, &X::value);
};

int
main(){
    X x;
    std::cout << x.get_value() << std::endl;
    x.set_value(-10);
    std::cout << x.get_value() << std::endl;
    return 0;
}

[出力]

42
-10


メンバ変数に auto が使えないのでそこはだいぶ残念な事になっているけど、それ以外はすっきりと書けますね。
ちなみに C++11 だと以下のような感じ。

#include <functional>
#include <iostream>


template<typename T, typename Type>
std::function<void(Type)>
setter(T* t, Type T::* member){
    return [=](Type x){
        t ->* member = x;
    };
}

template<typename T, typename Type>
std::function<Type()>
getter(T* t, Type T::* member){
    return [=]{
        return t ->* member;
    };
}


class X{
    int value = 42;
public:
    std::function<void(int)> set_value = setter(this, &X::value);
    std::function<int()> get_value = getter(this, &X::value);
};


int
main(){
    X x;
    std::cout << x.get_value() << std::endl;
    x.set_value(-10);
    std::cout << x.get_value() << std::endl;
    return 0;
}


std::function を使っているので利用する側は C++14 よりもすっきりしているという。
(まぁその分オーバーヘッドが発生するけども。