- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
Modern C++元编程应用
展开查看详情
1 .Modern C++元编程应用 祁宇 qicosmos@163.com purecpp.org 1
2 . 2018 中国C++大会—purecpp.org 模版元 2
3 .2018 中国C++大会—purecpp.org 3
4 .2018 中国C++大会—purecpp.org 4
5 . 2018 中国C++大会—purecpp.org !! 模版元 代码墙!! 在中国C++大会上?? 5
6 . 2018 中国C++大会—purecpp.org 元编程的缺点 ● 代码晦涩 ● 比较难写 ● 编译时间长 ● 糟糕的错误提示 6
7 . 2018 中国C++大会—purecpp.org 元编程的优点 ● zero-overhead 编译期计算 ● 简洁而优雅地解决问题 ● 终极抽象 Dream code! 7
8 .2018 中国C++大会—purecpp.org 8
9 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 ○ 元函数 ○ SFINAE ○ 模版递归 ○ 递归继承 ○ Tag Dispatch ○ 模版特化/偏特化 9
10 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 template<class T> struct add_pointer { typedef T* type; }; typedef typename add_pointer<int>::type int_pointer; 元函数:编译期函数调用的类或模版类– add_pointer 调用元函数:访问元函数的内部类型::type Type T作为元函数的value,类型是元编程中的一等公民 模版元编程概念上是函数式编程 10
11 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 template<bool B, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; template <class T> typename enable_if<sizeof(T)==4, void>::type foo(T t) {} foo(1); //ok foo('a'); //compile error SFINAE:替换失败不是一个错误,基于模版实例化的tag dispatch 11
12 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 template <int n> struct fact98 { static const int value = n * fact98<n - 1>::value; }; template <> struct fact98<0> { static const int value = 1; }; std::cout << fact98<5>::value << std::endl; 模版递归 12
13 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 模版元编程集大成者:boost.mpl, boost.fusion boost.mpl:编译期类型容器和算法 boost.fusion:通过异构的编译期容器融合编译期和运行期计算 struct print{ template <typename T> void operator()(T const& x) const{ std::cout << typeid(x).name() << std::endl; } }; template <typename Sequence> void print_names(Sequence const& seq){ for_each(filter_if<boost::is_class<_> >(seq), print()); } boost::fusion::vector<int, char, std::string> stuff(2018, 'i', "purecpp"); print_names(stuff); 13
14 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 Andrei Alexandrescu 14
15 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 template<class T> struct add_pointer { typedef T* type; }; typedef typename add_pointer<int>::type int_pointer; ● In C++11 template<class T> using add_pointer = T*; using int_pointer = add_pointer<int>; C++11 template aliases(模版别名) 元函数由类和类模版变为模版别名 15
16 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++11 template<typename... Values> struct meta_list {}; using list_of_ints = meta_list<char, short, int, long>; template<class List> struct list_size; template<template<class...> class List, class... Elements> struct list_size<List<Elements...>> : std::integral_constant<std::size_t, sizeof...(Elements)> {}; constexpr auto size = list_size<std::tuple<int, float, void>>::value; constexpr auto size1 = list_size<list_of_ints>::value; constexpr auto size2 = list_size<boost::variant<int, float>>::value; C++11 Variadic Templates Variadic templates作为类型容器 通过variadic templates pack访问模版参数,不通过模版递归和特化 16
17 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 C++11 type_traits提供了大量的元函数,让模版元编程变得更简单 17
18 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++98 template <int n> struct fact98 { static const int value = n * fact98<n - 1>::value; }; template <> struct fact98<0> { static const int value = 1; }; std::cout << fact98<5>::value << std::endl; ● In C++11 constexpr int fact11(int n) { return n <= 1 ? 1 : (n * fact11(n - 1)); } 18
19 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++11 constexpr int fact11(int n) { return n <= 1 ? 1 : (n * fact11(n - 1)); } ● In C++14 constexpr int fact14(int n) { int s = 1; for (int i = 1; i <= n; i++) { s = s * i; } return s; } 19
20 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++14 Everything changed in meta programming 新特性产生新的编程思想! constexpr, generic lambda, variable template Boost.hana Louis Dionne 20
21 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● Boost.hana template <typename T> struct type_wrapper { using type = T; }; template <typename T> type_wrapper<T> type{}; //type to value auto the_int_type = type<int>; //value to type using the_real_int_type = decltype(the_int_type)::type;
22 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● Boost.hana template <typename T> type_wrapper<T> type{}; constexpr auto add_pointer = [](auto t) { using T = typename decltype(t)::type; return type<std::add_pointer_t<T>>; //type to value }; constexpr auto intptr = add_pointer(type<int>); static_assert(std::is_same_v<decltype(intptr)::type, int*>); //value to type 元函数的定义不再是类了,而是lambda! generic lambda, variable template, constexpr functional programming
23 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● Boost.hana auto animal_types = hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Cat&>, hana::type_c<Dog*>); auto animal_ptrs = hana::filter(animal_types, [](auto a) { return hana::traits::is_pointer(a); }); static_assert(animal_ptrs == hana::make_tuple(hana::type_c<Fish*>, hana::type_c<Dog*>), ""); auto animals = hana::make_tuple(Fish{ "Nemo" }, Cat{ "Garfield" }, Dog{ "Snoopy" }); auto names = hana::transform(animals, [](auto a) { return a.name; }); assert(hana::reverse(names) == hana::make_tuple("Snoopy", "Garfield", "Nemo")); 通过类型容器融合编译期和运行期计算,替代boost.mpl和boost.fusion!
24 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● Boost.hana ○ 元函数不再是类或类模版,而是lambda ○ 不再基于类型,而是基于值 ○ 没有SFINAE,没有模版递归 ○ 函数式编程 ○ 代码更容易理解 ○ 元编程变得更简单 ○ 融合编译期与运行期
25 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++14 template<std::size_t I> auto& get(person& p); In C++17 template<> auto& get<0>(person& p) { template<std::size_t I> return p.id; auto& get(person& p) { } if constexpr (I == 0) { return p.id; template<> } auto& get<1>(person& p) { else if constexpr (I == 1) { return p.name; return p.name; } } else if constexpr (I == 2) { template<> return p.age; auto& get<2>(person& p) { } return p.age; } } 没有特化 25
26 . 2018 中国C++大会—purecpp.org Meta Programming编程思想 ● In C++14 template <typename T> std::enable_if_t<std::is_same_v<T, std::string>, std::string> to_string(T t){ return t; } template <typename T> std::enable_if_t<!std::is_same_v<T, std::string>, std::string> to_string(T t){ return std::to_string(t); } ● In C++17 template <typename T> std::string to_string(T t){ if constexpr(std::is_same_v<T, std::string>) return t; else return std::to_string(t); } No SFINAE 26
27 . 2018 中国C++大会—purecpp.org C++新标准新特性产生新的idea,让元编程变得更简单更强大 variable templates constexpr generic lambda SFINAE template aliases constexpr recursive variadic templates tag dispatch C++14 specialize C++11 C++98 Newer is Better! ● C++98: boost.mpl, boost.fusion ● C++11: boost.mp11, meta, brigand ● C++14: boost.hana 27
28 .2018 中国C++大会—purecpp.org 28
29 .静态检查 29