Hatena::ブログ(Diary)

C++でゲームプログラミング

2014-08-11

[]C++14 で名前付き引数

標準ライブラリでできる範囲で書いてみました。


[ソース]

#include <tuple>


template<typename T, typename Uniq>
struct holder{
    T value;
    operator T(){
        return value;
    }

    holder&
    operator =(T t){
        value = t;
        return *this;
    }
};


template<typename T, typename Uniq, typename ...Args>
T
get(holder<T, Uniq>, Args... args){
    return std::get<holder<T, Uniq>>(std::make_tuple(args...));
}


#include <iostream>
#include <string>

holder<int, struct age_> age;
holder<int, struct index_> id;
holder<std::string, struct name_> name;


template<typename ...Args>
void
func(Args... args){
    std::cout << "id = "    << ::get(id, args...)    << std::endl;
    std::cout << "age = "   << ::get(age, args...)   << std::endl;
    std::cout << "name = "  << ::get(name, args...)  << std::endl;
}


int
main(){
    func(age = 13, name = "homu", id = 0);
    func(id = 1, name = "mami", age = 14);
    return 0;
}

[出力]

id = 0
age = 13
name = homu
id = 1
age = 14
name = mami

思ったよりもスッキリと書くことができた。

C++14 依存といっても必要なのは std::get() の部分だけなのでそこを何とかすれば C++11 でも動作するはず。

デフォルト引数なんかに対応したい場合はもうちょっと工夫が必要かなー。

2014-08-10

[]std::unique のデフォルトのデリータ

std::unique のデフォルトのデリータは何なのか調べてみたら次のように定義されているみたい。



template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

template <
    class T,
    class Deleter
> class unique_ptr<T[],Deleter>;

と、いうことでデフォルトでは std::default_delete が使用されているみたいです。

std::default_delete<T> は delete を行うための関数オブジェクトで次のように利用できます。


[ソース]

#include <iostream>
#include <memory>

struct X{
    X(){
        std::cout << "new X" << std::endl;
    }
    ~X(){
        std::cout << "delete X" << std::endl;
    }
};

int
main(){
    std::cout << "start" << std::endl;
    auto xp = new X{};
    std::default_delete<X> deleter;
    deleter(xp);
    std::cout << "end" << std::endl;
    return 0;
}

[出力]

start
new X
delete X
end

std::default_delete<T> なんて標準ライブラリにあったのか。

2014-08-09

[]std::unique_ptr のデリータをあとから設定する

と、いうのが Lingr の C++ 部屋に貼られていたので覚書。


[ソース]

#include <memory>
#include <functional>
#include <iostream>

int
main(){
    auto p = std::unique_ptr<int, std::function<void(int*)>>{ new int{42}, std::default_delete<int>{} };

    // deleter を設定
    p.get_deleter() = [](int* p){
        std::cout << "call deleter" << std::endl;
        delete p;
    };

    std::cout << *p << std::endl;

    return 0;
}

[出力]

42
call deleter

get_deleter() は参照オブジェクトを返すのでこんな感じで代入する事ができます。

便利……なのかな?


[]std::unique_ptr のデリータをあとから設定する

と、いうのが Lingr の C++ 部屋に貼られていたので覚書。


[ソース]

#include <memory>
#include <functional>
#include <iostream>

int
main(){
    auto p = std::unique_ptr<int, std::function<void(int*)>>{ new int{42}, std::default_delete<int>{} };

    // deleter を設定
    p.get_deleter() = [](int* p){
        std::cout << "call deleter" << std::endl;
        delete p;
    };

    std::cout << *p << std::endl;

    return 0;
}

[出力]

42
call deleter

get_deleter() は参照オブジェクトを返すのでこんな感じで代入する事ができます。

便利……なのかな?

2014-08-05

[]Bugs Fixed in Visual Studio 2013 Update 3

http://blogs.msdn.com/b/vcblog/archive/2014/08/04/bugs-fixed-in-visual-studio-2013-update-3.aspx


最近の Visual Studio 事情はよく知らないのだけれどだいぶ修正されているみたい。

Visual Studio も気になる環境ではあるのだけどいかんせん自由に動作できる環境がないからなぁ…。

だれか Windows マシンくだしあ

2014-08-04

[]C++ で簡単にアクセッサを書けるようにしたかったけど Non-static data members で auto が使えなくて死んだ


class X{
    int value_ = 42;
public:
    auto value = accessor(this, &X::value_);
};

みたいな感じで書きたかった。


[ソース]

template<typename Class, typename T>
struct accessor_impl{
    Class* class_;
    T Class::* member;

    T operator ()() const{
        return class_ ->* member;
    }

    void operator ()(T const& t) const{
        class_ ->* member = t;
    }
};


template<typename Class, typename T>
accessor_impl<Class, T>
accessor(Class* class_, T Class::* member){
    return { class_, member };
}


class X{
    int value_ = 42;
public:
//  auto value = accessor(this, &X::value_);
    accessor_impl<X, int> value{ this, &X::value_ };
};


#include <iostream>

int
main(){
    X x;
    std::cout << x.value() << std::endl;

    x.value(72);
    std::cout << x.value() << std::endl;

    return 0;
}

[出力]

42
72

つらい。