27
Tickライブラリで遊ぼう 北陸 Kernel/VM 探検隊 #1

Tickライブラリで遊ぼう(C++)

  • Upload
    kotoji

  • View
    414

  • Download
    0

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Tickライブラリで遊ぼう(C++)

Tickライブラリで遊ぼう

北陸 Kernel/VM 探検隊 #1

Page 2: Tickライブラリで遊ぼう(C++)

自己紹介

2

@kotojpn

かわいい

Page 3: Tickライブラリで遊ぼう(C++)

Tickについて

• C++のコンセプトという機能をプリプロセッサやテンプレートを用いて実現している!

• http://ericniebler.com/ここの人が提案したコンセプトチェックの方法を基にしたライブラリ!

• pfultz2という人が作った!

ここ https://github.com/pfultz2/Tick

3

Page 4: Tickライブラリで遊ぼう(C++)

補足: コンセプトとは

•ジェネリックな型が満たすべき要件定義のこと!e.g. ! 型 T は Forward Iterator のコンセプトを満たす!

!• C++11の時点で提案はされていたもののずいぶん揉めた結果入らなかった!

• C++17で入ればいいなあ

4

Page 5: Tickライブラリで遊ぼう(C++)

Tick解説

面白そうなのでTickについて調べてみたよ

5

Page 6: Tickライブラリで遊ぼう(C++)

Tick解説

•作者の github に書かれている例!

!!インクリメント可能か調べる特性メタ関数!

is_incrementable<T>!!

次のように書ける

6

Page 7: Tickライブラリで遊ぼう(C++)

Tick解説

Tickを使った is_incrementable<T> の定義!

7

#include <tick/requires.h> #include <tick/trait_check.h> !TICK_TRAIT(is_incrementable) { template <class T> auto requires_(T&& x) -> TICK_VALID( ++x, x++ ); };

Page 8: Tickライブラリで遊ぼう(C++)

Tick解説

マクロを展開してみる!

8

!struct tick_private_trait_base_is_incrementable : tick::ops { typedef tick::refines<> type; }; struct tick_private_trait_is_incrementable; template<class... T> struct is_incrementable : tick::models<tick_private_trait_is_incrementable(T...)> {}; !struct tick_private_trait_is_incrementable : tick::detail::base_requires, tick::ops, tick_private_trait_base_is_incrementable::type { template<class T> auto requires_(T&& x) -> decltype(tick::detail::valid_expr((x++, ++x, tick::detail::void_()))); };

Page 9: Tickライブラリで遊ぼう(C++)

Tick解説

わかりにくいので書き換え!!!!!!!!

9

template<class... Ts> struct holder { using type = void; }; !template <class Trait, class X = void> struct models : false_type {}; !template <class Trait, class T> struct models<Trait(T), typename holder< decltype(declval<Trait>().requires_(declval<T>())) >::type> : true_type {}; !struct is_incrementable_impl { template <class T> auto requires_(T&& x) -> decltype(x++, ++x); }; !template <class T> struct is_incrementable : models<is_incrementable_impl(T)> {};

Page 10: Tickライブラリで遊ぼう(C++)

Tick解説

わかりやすくなったのか???!!

• とりあえず太線にしたところが重要

10

Page 11: Tickライブラリで遊ぼう(C++)

Tick解説(削除ページ)

補足: この場合はこう書いたほうが楽!

8

!struct is_incrementable_impl { template <class T> static auto check(T*) -> decltype( std::declval<T&>()++, ++std::declval<T&>(), std::true_type()); ! static auto check(...) -> std::false_type; }; !template <class T> struct is_incrementable : decltype(is_incrementable_impl::check<T>(nullptr)) {};

Page 12: Tickライブラリで遊ぼう(C++)

Tick解説

11

一方, これを利用するを使う関数は

Page 13: Tickライブラリで遊ぼう(C++)

Tick解説

• is_incrementable<T> を使った関数!

!!!!!!!TICK_REQUIRESマクロに特性メタ関数をいれればOK

12

!template < class T, TICK_REQUIRES(is_incrementable<T>::value) > void increment(T& x) { x++; }

Page 14: Tickライブラリで遊ぼう(C++)

Tick解説

•これもマクロ展開してみる!!!!!!!!

enable_if 使ってるだけ13

!Template< class T, typename std::enable_if<is_incrementable<T>::value, int>::type = 0) > void increment(T& x) { x++; }

Page 15: Tickライブラリで遊ぼう(C++)

Tick解説

もう少し複雑なものをも簡潔に書けるよ!!

14

Page 16: Tickライブラリで遊ぼう(C++)

Tick解説

• 多少複雑な例 ( has_hoge )!

!has_hoge<T> の要件!

• 型 T がメンバ関数 hoge() をもっている!

• その返り値が int型である

15

Page 17: Tickライブラリで遊ぼう(C++)

Tick解説

has_hoge<T> の例

16

#include <tick/requires.h> #include <tick/trait_check.h> !TICK_TRAIT(has_hoge) { template <class T> auto requires_(T&& x) -> TICK_VALID( returns<int>(x.hoge()) ); };

Page 18: Tickライブラリで遊ぼう(C++)

Tick解説

• 他にも様々な機能があります!• 作者のgithubのREADMEがかなり充実している!

• なので, そちらを参考にしたほうが早い...

17

Page 19: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

• 実際に型制約を Tick で書き換えてみたよ!

!ここの point_traits の型制約!

https://gist.github.com/kotoji/af5485cef6e98466328e

18

Page 20: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

• 実際に型制約を Tick で書き換えてみたよ!!

!!

こんな感じ

19

Page 21: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

point_trait<T> の型制約

20

namespace util { namespace detail { namespace mpl = boost::mpl; !template <typename Cond, typename Seq, std::size_t I> struct any_impl { static constexpr bool value = mpl::apply<Cond, typename std::tuple_element<I, Seq>::type >::type::value && any_impl<Cond, Seq, I - 1>::value; }; template <typename Cond, typename Seq> struct any_impl<Cond, Seq, 0> { static constexpr bool value = mpl::apply<Cond, typename std::tuple_element<0, Seq>::type >::type::value; }; } // namespace detail template <typename Cond, typename... Types> struct any_ : detail::any_impl<Cond, std::tuple<Types...> , sizeof...(Types) - 1> {}; } // namespace util template <typename T, typename U = decltype(std::declval<T>().x), typename U1 = decltype(std::declval<T>().y), std::enable_if<util::any_<std::is_floating_point<boost::mpl::_1> ,U, U1>::value && std::is_default_constructible<T>::value >::type* = nullptr > struct point_traits { // 実装略

};

Page 22: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

うわあ

21

Page 23: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

一応説明!point_traits<T> の型制約!

• T は実数型のメンバ変数 x を持つ!

• T は実数型のメンバ変数 y を持つ!

• T は default constructible である!• それ以外の場合は自分でアダプトしてね

22

Page 24: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

Tickで新しくなった point_traits

23

TICK_TRAIT(has_x) { template <class T> auto requires_(T&& p) -> TICK_VALID( returns<std::is_floating_point<_>>(p.x) ); }; !TICK_TRAIT(has_y) { template <class T> auto requires_(T&& p) -> TICK_VALID( returns<std::is_floating_point<_>>(p.y) ); }; template <class T, TICK_REQUIRES(has_x<T>() and has_y<T>() and std::is_default_constructible<T>::value) > struct point_traits { // 実装略 };

Page 25: Tickライブラリで遊ぼう(C++)

Tickで遊ぶ

もともとのコードがアレだったとはいえ!Tick を使って簡潔に書くことが出来た!

ウレシイヤッター

24

Page 26: Tickライブラリで遊ぼう(C++)

Tickまとめ

• 特性メタ関数が割りと簡単に書ける!• TICK_REQUIRES マクロに特性メタ関数を並べるだけで色々な制約を組み合わせ可能!!

25

Page 27: Tickライブラリで遊ぼう(C++)

Tickまとめ

色々な型制約を組み合わせて!君だけのコンセプトをつくろう

26