cpp模板编程
文章平均质量分 53
提供cpp模板编程的完全解析和demo
前提知识:读过《STL源码解析》,或者《effective modern cpp》
infralan
Major in:linux内核 虚拟化 云原生,熟悉:分布式、网络、存储,感兴趣:计算、数据库、机器学习系统。
展开
-
模板编译的过程
模板编译的过程太复杂了。以下只是我个人见解,可能有不对的地方。模板只应用于“编译”阶段,就像宏只应用于“预处理”阶段一样。千万别和“链接”阶段和“运行”阶段搞混。我简单说一下函数模板的实例化过程吧。名字查找名字查找,是当程序中出现一个名字时,将其与引入它的声明联系起来的过程。对于模板来说,一个名字可以有多个声明。对于函数而言,这有一个天坑“参数依赖查找”。参数依赖查找可能会引入新的声明,从而可能改变重载集,简直是万恶之源。这里就先不说参数依赖查找了。模板实参推导找到名字的多个声明之后,我们要对函数原创 2021-07-09 23:24:42 · 500 阅读 · 0 评论 -
类型推导精髓
类型推导精髓back to the basic求解未知方程,已知形参和实参,以及一些规则,推最好的那个符合case1形参 T& param实参 int x那么T就是int。形参 T& param实参 const int xT 是const int形参是T& param实参是const int &T 是 const int注意,int类型天然可以转换为int& 类型,而如果位置上有&,那么T自然可以少做这个原创 2021-07-09 17:58:10 · 58 阅读 · 0 评论 -
std::is_same和std::decay demo
C++11的模板类型判断——std::is_same和std::decay问题提出:有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢?如:#include <iostream>template<typename TYPE>void typeCheck(TYPE data){ //do something check data type //std::cout<原创 2021-07-09 12:34:25 · 122 阅读 · 2 评论 -
SFINAE和enable_if
SFINAE和enable_ifSFINAESFINAE可以说是C++模板进阶的门槛之一,如果选择一个论题来测试对C++模板机制的熟悉程度,那么在我这里,首选就应当是SFINAE机制。我们不用纠结这个词的发音,它来自于 Substitution failure is not an error 的首字母缩写。这一句之乎者也般难懂的话,由之乎者 —— 啊,不,Substitution,Failure和Error三个词构成。我们从最简单的词“Error”开始理解。Error就是一般意义上的编译错误。一旦出原创 2021-07-09 09:25:26 · 386 阅读 · 2 评论 -
boost::function的简单实现demo
boost::function的简单实现demo前言boost::function和boost:bind是一对强大的利器。相信用过的童鞋多少有些体会。虽然平时在用boost::function,但是用的时候心中总会一些不安,因为不知道它是怎么实现的。于是,就自己琢磨着简单的实现一下,搞明白基本的原理。对于这个简单实现,有以下几个目标:选取比较常见的接收2个参数的情况。支持普通函数/函数指针、成员函数指针。兼容函数对象、函数适配器/boost::bind。实现首先,定义一个基类:tem原创 2021-07-08 11:38:00 · 192 阅读 · 0 评论 -
boost::bind的简单实现
boost::bind的简单实现前言在上一篇blog中简单的实现了boost::function,支持带有2个参数的函数/函数指针,函数对象,函数适配器/bind类,以及带有1个参数的成员函数指针。本文接着来介绍如何实现一个简单的boost::bind。基本目标如下:支持接收0个参数的函数/函数指针,函数对象。支持接收1个参数的函数/函数指针,函数对象。支持接收2个参数的函数/函数指针,函数对象。实现首先,解决占位符的问题:namespace{ struct Placehold原创 2021-07-08 11:42:07 · 116 阅读 · 0 评论 -
从1打印N demo
像递归一样的函数模板调用遇到一个蛮奇葩的问题:在 C++ 中如何不用循环和递归,打印从 1 至 N 的自然数?想了想,用模板元编程可以解决——让编译器在编译期把该打印的东西都展开就好了。直接上代码好了……#include <iostream>template <int N>void counting(std::ostream& os) { counting<N - 1>(os); // * os << N << st原创 2021-07-05 00:08:47 · 57 阅读 · 0 评论 -
SFINAE demo1
什么是SFINAE?匹配失败不是错误简单来说,C++找重载的时候,会一个个代入检查函数声明和调用是不是能匹配,找到唯一正确的就行了。代入检查过程中产生的语义错误都会被忽略。quick viewSFINAE 技术,即匹配失败不是错误,英文Substitution Failure Is Not An Error,其作用是当我们在进行模板特化的时候,会去选择那个正确的模板,避免失败看个具体的例子:long multiply(int i, int j) { return i * j; }templa原创 2021-07-05 00:07:14 · 80 阅读 · 0 评论 -
C++ 编译期 parser combinator 实现计算器
C++ 编译期 parser combinator 实现计算器详细注释//g++ test.cpp -std=c++17#include <type_traits>namespace mx {//定义两个基类,stream和intstemplate <char...>struct stream { using stream_type = stream;};template <auto...>struct ints { usin原创 2021-07-05 00:06:37 · 184 阅读 · 0 评论 -
可变模板参数demo2
可变模板参数demo2转载于https://www.cnblogs.com/qicosmos/p/4325949.html 修复了一些错误参数包的展开可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号“…”。比如我们常常这样声明一个可变模版参数:template<typename...>或者template<class...>,一个典型的可变模版参数的定义是这样的:template <class原创 2021-07-04 14:25:59 · 108 阅读 · 2 评论 -
类型判断的traits类demo
类型判断的traits类测试代码#include <iostream>using namespace std;int main(){ cout << std::is_void<void>::type::value << endl; cout << std::is_void<bool>::value << endl;}输出结果10解释一下,is_void类可以判断模板参数的类型,使用很简原创 2021-07-04 12:16:41 · 69 阅读 · 0 评论 -
偏特化实现switch demo
偏特化实现switch编译期运行。代码#include <iostream>using namespace std;template <int v>class Case {public: static inline void Run() { cout << "default case" << endl; }};template <>class Case<1> {public:原创 2021-07-04 12:08:50 · 72 阅读 · 0 评论 -
偏特化实现if demo
偏特化实现if将if语句放在编译期执行,可以用模板特化的方式实现。下面是实现代码#include <iostream>using namespace std;template <bool condition>class If {public: static inline void Run() { cout << "it's true" << endl; }};template <>clas原创 2021-07-04 11:49:57 · 45 阅读 · 0 评论 -
循环展开demo
循环展开demo代码#include <iostream>using namespace std;template <int N>class Loop {public: static inline int Run() { int v = Loop<N - 1>::Run(); cout << v; return v + 1; }};template <>cl原创 2021-07-04 11:45:50 · 155 阅读 · 0 评论 -
C++ print tuple demo
C++ print tuplestd::tuple不支持输入输出,就想实现一下。最初想用模板函数实现,无奈总是不行,就改用模板类了,下面是实现代码。#include <iostream>#include <tuple>using namespace std;template <class Tuple, size_t N>struct print_imp { static void print(ostream& out, const Tuple原创 2021-07-04 11:40:21 · 285 阅读 · 0 评论 -
enum做数值计算demo
enum做数值计算enum的值由编译器在编译期计算利用模板特化和递归算法,可以让编译器在计算enum值的时候递归产生一系列class下面是简单的例子, 一个求N的阶乘的代码:#include <iostream>template <int N>class Factorial {public: enum { RESULT = N * Factorial<N - 1>::RESULT };};template <>class F原创 2021-07-04 11:38:07 · 85 阅读 · 0 评论 -
tuple和vector解包当做参数传入到函数中demo
tuple和vector解包当做参数传入到函数中在C++中,有一些情况下,我们需要将tuple或者vector中的值当做参数传递到一个函数当中,传统的做法如下:std::vector<int> v;call(v[0], v[1], v[2]);auto r = std::make_tuple(1, 2.1, 1ull)call(std::get<0>(r), std::get<1>(r), std::get<2>(r));我们可以通过如下的方式原创 2021-07-04 11:28:03 · 638 阅读 · 0 评论 -
integral_constant类demo
integral_constant类这个类是所有traits类的基类,分别提供了以下功能:value_type 表示值的类型value表示值type 表示自己, 因此可以用::type::value来获取值true_type和false_type两个特化类用来表示bool值类型的traits,很多traits类都需要继承它们下面的代码分别来自C++11和Boost,略有差别:C++11包含value_type()函数,返回真正的valueC++11用constexpr关键字表示在编译期原创 2021-07-04 11:17:41 · 213 阅读 · 0 评论 -
可变模板参数demo1
Gemfield可变模板参数作者:Gemfield链接:https://zhuanlan.zhihu.com/p/104450480 来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。背景一切都从函数传参开始说起。我们知道,在C语言中有个神奇的函数:printf:printf("%s : %d\n","gemfield number",7030);这个函数可以传递可变参数,说到“可变”参数,主要是指两点可变:1,参数数量可变;2,参数类型可变。比如上面演示的C库原创 2021-07-04 00:52:02 · 103 阅读 · 3 评论 -
tuple用法简介demo
tuple用法简介这次要讲的内容是:c++11中的tuple(元组)。tuple看似简单,其实它是简约而不简单,可以说它是c++11中一个既简单又复杂的东东,关于它简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多细节,要揭开它神秘的面纱时又比较困难。tuple是一个固定大小的不同类型值的集合,是泛化的std::pair。和c#中的tuple类似,但是比c#中的tuple强大得多。我们也可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观原创 2021-07-02 13:13:38 · 298 阅读 · 0 评论 -
在 C++ 中解包 std::vector 作为函数参数demo
在 C++ 中解包 std::vector 作为函数参数转载于 https://liam.page/2019/07/04/unpack-vector-as-parameters-for-functions/修正了一些typo有一个接受若干个同类型参数的函数 template <typename U, typename T> U func(T a, T b, T c),现在有一个 std::vector<T> args,希望将 std::vector<T> 当中的原创 2021-07-02 14:51:29 · 629 阅读 · 0 评论 -
获取函数的参数数量和返回值类型demo
获取函数的参数数量和返回值类型有的时候,我们由于某一些特殊的需求,希望获取一个函数的返回值类型,或者是参数数量,可以借助模板来实现。假如我们有一个函数int f(double, float) { return 1;}返回值类型当我们需要获取返回值类型的时候,我们首先声明一个模板函数。template <class R, class... Args>R getRetValue(R(*)(Args...));上面R(*)(Args...)定义了一个函数指针。或者tem原创 2021-07-02 14:42:21 · 568 阅读 · 0 评论 -
tuple的高级用法demo
我前面说过tuple是简约而不简单。它有很多高级的用法。它和模板元关系密切,要介绍它的高级用法的时候,读者需要一定的模板元基础,如果你只是把它当一个泛型的pair去使用时,这部分可以不看,如果你想用它高级用法的时候就往下看。让我们要慢慢揭开tuple神秘的面纱。tuple的高级用法获取tuple中某个位置元素的类型通过std::tuple_element获取元素类型。template<typename Tuple>void Fun(Tuple& tp){ std::t原创 2021-07-02 13:43:03 · 168 阅读 · 1 评论