13 | 编译期能做些什么?一个完整的计算世界
该思维导图由 AI 生成,仅供参考
编译期计算
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了C++模板元编程的基本概念和应用。模板元编程允许在编译期间进行各种计算,实现了一个完整的图灵机,能够实现诸如阶乘计算、条件语句、循环等复杂计算。文章通过示例代码展示了如何使用模板元编程进行编译期计算,包括阶乘函数的实现、条件语句模板的定义、循环模板的使用以及整数常数模板的应用。此外,还介绍了如何使用模板元编程进行从1加到n的计算。读者可以了解模板元编程的强大威力,以及如何在C++中利用模板进行编译期计算。文章还指出了一些需要注意的细节,如使用`static_assert`来确保参数永远不会是负数,以及在使用`::`取一个成员类型时需要额外加上`typename`关键字。最后,文章提到了在现代C++中不使用模板元编程的方式也能达到同样的效果,为读者展示了模板元编程的发展方向。整体来说,本文通过具体的例子和技术细节,生动地展示了C++模板元编程的应用和潜力。
《现代 C++ 编程实战》,新⼈⾸单¥59
全部留言(29)
- 最新
- 精选
- 禾桃脑壳儿疼的兄弟姐妹们,我这有个小偏方, 哈哈 While< Sum<2>::type >::type::value 实例化(instantiation)过程 --> While< SumLoop<0, 2> >::type::value --> WhileLoop<SumLoop<0, 2>::cond_value, SumLoop<0, 2>>::type::value --> WhileLoop<true, SumLoop<0, 2>>::type::value --> WhileLoop<SumLoop<0, 2>::cond_value, SumLoop<0, 2>::next_type>::type::value --> WhileLoop<true, SumLoop<2, 1>>::type::value --> WhileLoop<SumLoop<2, 1>::cond_value, SumLoop<2, 1>::next_type>::type::value --> WhileLoop<true, SumLoop<3, 0>>::type::value --> WhileLoop<SumLoop<3, 0>::cond_value, SumLoop<3, 0>::next_type>::type::value --> WhileLoop<false, SumLoop<3, -1>>::type::value --> SumLoop<3, -1>::res_type::value -->integral_constant<int, 3>::value -->3
作者回复: 对,对于模板,就是要在脑子里或纸上、电脑上把它展开……☺️
2019-12-25317 - 总统老唐记得吴老师之前预告过,这一节可能会比较难,确实被难住了。在第一个 If 模板这里就被卡住了,老师能给个简单的例子来说明这个 If 模板该如何使用么?
作者回复: 下面的函数和模板是基本等价的: int foo(int n) { if (n == 2 || n == 3 || n == 5) { return 1; } else { return 2; } } template <int n> struct Foo { typedef typename If< (n == 2 || n == 3 || n == 5), integral_constant<int, 1>, integral_constant<int, 2>>::type type; }; 你可以输出 foo(3),也可以输出 Foo<3>::type::value。
2019-12-258 - chang比如,如果我们对 const string& 应用 remove_const,就会得到 string&,即,remove_const::type 等价于 string&。 remove_const只能去顶层const。const string&应用remove_const后还是const string&,const string应用remove_const后是string。
作者回复: 谢谢抓虫🙏。
2021-06-034 - 莫言template < template <typename, typename> class OutContainer = vector, typename F, class R> 请问老师,这个OutConContainer前面的template<typename,typename>应该怎么理解
作者回复: 模板的参数可以是类型(如 int),可以是值(如长度 8),也可以是其他(类或别名)模板。这个语法代表 OutContainer 是一个带两个类型模板参数的(类或别名)模板。(vector 有两个类型模板参数,第二个有默认值,一般不需要自己提供。)
2021-12-272 - YouCompleteMetemplate <typename Body> struct whileLoop<true, Body> 部分似乎改成下面这样,更直观, 编译时计算更少呢 template <typename Body> struct whileLoop<true, Body> { typedef typename whileLoop< Body::next_type::cond_value, typename Body::next_type>::type type; };
作者回复: 嗯,是的,你的写法能少展开一次。👍
2020-01-162 - 李云龙分享一下我的代码:实现求最大公约数的辗转相除法 template <bool Cond, typename Body> struct WhileLoop; template <typename Body> struct WhileLoop<true, Body> { typedef typename WhileLoop<Body::Cond, typename Body::NextType>::type type; }; template <typename Body> struct WhileLoop<false, Body> { typedef typename Body::ResType type; }; template <typename Body> struct While { typedef typename WhileLoop<Body::Cond, Body>::type type; }; template <typename T, T val> struct integer { typedef T ValueType; static const T Value = val; typedef integer type; }; template <int lhs, int rhs> struct GCD { static const bool Cond = lhs % rhs != 0; static const int result = lhs; typedef integer<int, result> ResType; typedef GCD<rhs, lhs % rhs> NextType; }; int main() { cout << While<GCD<100, 56>>::type::Value << endl; return 0; }
作者回复: 我测试了一下,似乎不行? 我就前面加了 <iostream> 的包含和 using。然后就报错了。
2023-10-14归属地:北京31 - Geek_15f2c9老师,对万能引用使用完美转发是否好点,result.push_back(std::forward<decltype(f(item))>(f(item)))或result.emplace_back(std::forward<decltype(f(item))>(f(item)));;
作者回复: 很好的问题。但是,实际必要性不高。 原因是,f(…) 极少会有合法的、返回右值引用的场景。唯一我能想到的可能性是返回值是根据输入的右值生成的情况。这样的话,得保证在输入是个右值容器时传递元素的右值给 f,所以真要考虑这种情况的话,代码比你写的还要再复杂不少……
2021-04-281 - Gazelle我实践写了下remove_const,好像没有把const去掉。这里是不是有点问题呢? https://stackoverflow.com/questions/15887144/stdremove-const-with-const-references 我看这里说是如果同时有const和引用的话,还需要去掉引用? std::remove_const<std::remove_reference<const string&>::type>::type
作者回复: 这里有个小细节:const T& 等同于 T const&,但和 T& const 不同。前者是一个指向常量的引用,后者是一个常引用。只有后者才被看作是一个“常量”。
2020-11-291 - 鲁·本对While<Sum<10>::type>::type::value进行手动推导,最终是能推导出实际语句是 integral_constant<int,10+9+...1>::value的,但让我独立写出 完整的代码是万万不能的😄
作者回复: 哈哈,我写的时候头也很大。只是为了说明能写出来,而不是真想/需要这么写。
2020-10-111 - 吃鱼“如果要得到布尔值的话,当然使用 `is_trivially_destructible::value` 就可以,但此处不需要。需要的是,使用 `()` 调用该类型的构造函数,让编译器根据数值类型来选择合适的重载。这样,在优化编译的情况下,编译器可以把不需要的析构操作彻底全部删除。” 老师,这里没太懂,使用 `()` 调用该类型的构造,这里的调用是在哪里调用,为什么 destroy 要调用构造函数
作者回复: 指的就是这句: _destroy(ptr, is_trivially_destructible<T>()) 这儿构造了一个 true_type 或 false_type 的对象,然后编译器会根据第二个参数的类型,决定调用 _destroy 的哪个重载。
2020-06-0231