Upload
kotoji
View
414
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Citation preview
Tickライブラリで遊ぼう
北陸 Kernel/VM 探検隊 #1
自己紹介
2
@kotojpn
かわいい
Tickについて
• C++のコンセプトという機能をプリプロセッサやテンプレートを用いて実現している!
• http://ericniebler.com/ここの人が提案したコンセプトチェックの方法を基にしたライブラリ!
• pfultz2という人が作った!
ここ https://github.com/pfultz2/Tick
3
補足: コンセプトとは
•ジェネリックな型が満たすべき要件定義のこと!e.g. ! 型 T は Forward Iterator のコンセプトを満たす!
!• C++11の時点で提案はされていたもののずいぶん揉めた結果入らなかった!
• C++17で入ればいいなあ
4
Tick解説
面白そうなのでTickについて調べてみたよ
5
Tick解説
•作者の github に書かれている例!
!!インクリメント可能か調べる特性メタ関数!
is_incrementable<T>!!
次のように書ける
6
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++ ); };
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_()))); };
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)> {};
Tick解説
わかりやすくなったのか???!!
• とりあえず太線にしたところが重要
10
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)) {};
Tick解説
11
一方, これを利用するを使う関数は
Tick解説
• is_incrementable<T> を使った関数!
!!!!!!!TICK_REQUIRESマクロに特性メタ関数をいれればOK
12
!template < class T, TICK_REQUIRES(is_incrementable<T>::value) > void increment(T& x) { x++; }
Tick解説
•これもマクロ展開してみる!!!!!!!!
enable_if 使ってるだけ13
!Template< class T, typename std::enable_if<is_incrementable<T>::value, int>::type = 0) > void increment(T& x) { x++; }
Tick解説
もう少し複雑なものをも簡潔に書けるよ!!
14
Tick解説
• 多少複雑な例 ( has_hoge )!
!has_hoge<T> の要件!
• 型 T がメンバ関数 hoge() をもっている!
• その返り値が int型である
15
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()) ); };
Tick解説
• 他にも様々な機能があります!• 作者のgithubのREADMEがかなり充実している!
• なので, そちらを参考にしたほうが早い...
17
Tickで遊ぶ
• 実際に型制約を Tick で書き換えてみたよ!
!ここの point_traits の型制約!
https://gist.github.com/kotoji/af5485cef6e98466328e
18
Tickで遊ぶ
• 実際に型制約を Tick で書き換えてみたよ!!
!!
こんな感じ
19
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 { // 実装略
};
Tickで遊ぶ
うわあ
21
Tickで遊ぶ
一応説明!point_traits<T> の型制約!
• T は実数型のメンバ変数 x を持つ!
• T は実数型のメンバ変数 y を持つ!
• T は default constructible である!• それ以外の場合は自分でアダプトしてね
22
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 { // 実装略 };
Tickで遊ぶ
もともとのコードがアレだったとはいえ!Tick を使って簡潔に書くことが出来た!
ウレシイヤッター
24
Tickまとめ
• 特性メタ関数が割りと簡単に書ける!• TICK_REQUIRES マクロに特性メタ関数を並べるだけで色々な制約を組み合わせ可能!!
25
Tickまとめ
色々な型制約を組み合わせて!君だけのコンセプトをつくろう
26